一、动态语言相关概念

1.1 动态语言

  • 在运行时代码可以根据某些条件改变自身结构
  • 可以在运行时引进新的函数、对象、甚至代码,可以删除已有的函数等其他结构上的变化
  • 常见的动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang

1.2 动态类型语言

  • 在运行期间检查数据类型的语言
  • 数据类型不是在编译阶段决定的,而是把类型绑定延后到了运行阶段
  • 常见的动态类型语言:Python、Ruby、Erlang、JavaScript、swift、PHP、Perl

1.3 强类型语言

  • 一旦一个变量被指定了某个数据类型,如果不经过强制类型转换,那么它就永远是这个数据类型
  • 常见的强类型语言:Java、C#、Python、Object-C、Ruby

Python是动态语言,动态类型语言,也是强类型语言。所以Python可以在运行时改变自身结构,动态添加/删除属性和方法。接下来将介绍Python如何动态添加属性和方法。

二、动态添加属性

2.1 添加对象属性

class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge zhangsan = Person("张三", 18)
zhangsan.addr = "北京" # 类对象zhangsan动态添加对象属性addr
print(zhangsan.name) # 张三
print(zhangsan.age) #
print(zhangsan.addr) # 北京 lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) #
print(lisi.addr) # 'Person' object has no attribute 'addr'

由以上代码可知,Person类有两个属性:name和age。通过[对象名.属性名]给类对象zhangsan动态添加了对象属性addr,而Person的另一个类对象lisi却不能调用这个属性。

注:通过对象名添加的对象属性,只有这个对象能使用

2.2 添加类属性

class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge Person.addr = "北京" # 类Person动态添加类属性addr zhangsan = Person("张三", 18)
print(zhangsan.name) # 张三
print(zhangsan.age) #
print(zhangsan.addr) # 北京 lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) #
print(lisi.addr) # 北京

由以上代码可知,通过[类名.属性名]给类Person动态添加了类属性addr,Person的类对象zhangsan和lisi都能调用这个属性

注:通过类名添加的类属性,这个类的所有对象都能使用

三、动态添加方法

类中有三种方法,实例方法,静态方法和类方法,三种方法的区别如下:

  • 实例方法:需要绑定要一个对象上,第一个参数默认使用self,会把对象作为第一个参数传递进来
  • 静态方法:使用装饰器@staticmethod进行定义,类和对象都可以调用,不需要默认参数
  • 类方法:使用装饰器@classmethod进行定义,类和对象都可以调用,第一个参数默认使用cls,会把类作为第一个参数传递进来

3.1 添加实例方法

import types

class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge def eat(self):
print("---正在吃---") def run(self):
print("---正在跑---") zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.run = types.MethodType(run, zhangsan) # 类对象zhangsan动态添加对象方法run()
zhangsan.run() # ---正在跑--- lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.run() # 'Person' object has no attribute 'run'

由以上代码可知,Person类有一个方法:eat()方法。通过[types.MethodType(方法名, 对象名)]给类对象zhangsan动态添加了对象方法run(),同理,Person的另一个类对象lisi不能调用这个方法

注:通过对象名添加的对象方法,只有这个对象能使用

3.2 添加静态方法

class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge def eat(self):
print("---正在吃---") @staticmethod
def staticRun():
print("---正在跑---") Person.staticRun = staticRun # 类Person动态添加静态方法staticRun() Person.staticRun() # ---正在跑--- zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.staticRun() # ---正在跑--- lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.staticRun() # ---正在跑---

由以上代码可知,通过[类名.静态方法名]给类Person动态添加了静态方法staticRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法

注:通过类名添加的静态方法,这个类及这个类的所有对象都能使用

3.3 添加类方法

class Person(object):
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge def eat(self):
print("---正在吃---") @classmethod
def classRun(cls):
print("---正在跑---") Person.classRun = classRun # 类Person动态添加类方法classRun() Person.classRun() # ---正在跑--- zhangsan = Person("张三", 18)
zhangsan.eat() # ---正在吃---
zhangsan.classRun() # ---正在跑--- lisi = Person("李四", 28)
lisi.eat() # ---正在吃---
lisi.classRun() # ---正在跑---

由以上代码可知,通过[类名.类方法名]给类Person动态添加了类方法classRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法

注:通过类名添加的类方法,这个类及这个类的所有对象都能使用

四、__slots__的使用

通过以上内容,我们知道了如何动态的添加属性和方法。但是,如果我们想要限制class的属性该怎么办?例如:只允许Person实例添加name和age属性。为了达到这个目的,Python允许在定义class的时候,定义一个特殊变量__slots__来限制该class能添加的属性。

import types
class Person(object):
__slots__ = ("name", "age")  # 定义__slots__
def __init__(self, newName, newAge):
self.name = newName
self.age = newAge def eat(self):
print("---正在吃---") def run(self):
print("---正在跑---") Person.num = 100 # 类Person动态添加类属性num zhangsan = Person("张三", 18)
print(zhangsan.name) # 张三
print(zhangsan.age) #
print(zhangsan.num) #
zhangsan.eat() # ---正在吃--- zhangsan.addr = "北京" # 'Person' object has no attribute 'addr'
zhangsan.run = types.MethodType(run, zhangsan) # 'Person' object has no attribute 'run'

通过以上代码可知,__slots__对Person类的动态添加没有限制,而Person类对象zhangsan不能再动态添加对象属性和方法。

对于__slot__有以下几个需要注意的地方:

  • __slots__只对类对象进行限制,不对类进行限制
  • __slots__不仅限制类对象的属性,还限制类对象的方法
  • __slots__仅对当前类起作用,对继承的子类不起作用
  • 在子类中定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的__slots__

我的Python学习笔记(四):动态添加属性和方法的更多相关文章

  1. python学习笔记8--面向对象--属性和方法详解

    属性: 公有属性  (属于类,每个类一份) 普通属性  (属于对象,每个对象一份) 私有属性    (属于对象,跟普通属性相似,只是不能通过对象直接访问) 方法:(按作用) 构造方法 析构函数 方法: ...

  2. day_5.26python动态添加属性和方法

    python动态添加属性和方法 既然给类添加⽅法,是使⽤ 类名.⽅法名 = xxxx ,那么给对象添加⼀个⽅法 也是类似的 对象.⽅法名 = xxx '''2018-5-26 13:40:09pyth ...

  3. js对象动态添加属性,方法

    1. 动态添加属性,方法 var object = new Object(); object.name = "name"; object.age = 19; >>> ...

  4. Python学习笔记四:面向对象编程

    一:定义类并创建实例 Python中定义类,通过class关键字,类名开头大写,参数列表为所继承的父类.如果没有需要明确继承的类,则继承object. 使用类来创建对象,只需 类名+() 形式即可,p ...

  5. Python笔记_第三篇_面向对象_8.对象属性和类属性及其动态添加属性和方法

    1. 对象属性和类属性. 我们之前接触到,在类中,我们一般都是通过构造函数的方式去写一些类的相关属性.在第一次介绍类的时候我们把一些属性写到构造函数外面并没有用到构造函数,其实当时在写的时候,就是在给 ...

  6. python动态添加属性和方法

    ---恢复内容开始--- python动态添加属性: class Person(object): def __init__(self,newName,newAge): self.name = newN ...

  7. python 动态添加属性及方法及“__slots__的作用”

    1.动态添加属性 class Person(object): def __init__(self, newName, newAge): self.name = newName self.age = n ...

  8. Python基础之动态添加属性,方法,动态类,静态类

    ## 动态添加属性class Person: def __init__(self,name): self.name = name# 1.通过对象.属性名称来操作p = Person('KTModel' ...

  9. JS内置对象的原型不能重定义?只能动态添加属性或方法?

    昨天马上就快下班了,坐在我对面的同事突然问我一个问题,我说“爱过”,哈哈,开个玩笑.情况是这样的,他发现JS的内置对象的原型好像不能通过字面量对象的形式进行覆盖, 只能动态的为内置对象的原型添加属性或 ...

随机推荐

  1. 二叉树的递归遍历 天平UVa839

    题意:输入一个树状的天平,利用杠杆原理,根据力矩是否相等(W1D1==W1D2)判断天平是否平衡 解题思路:1.由于判断天平是否平衡,当W1和W2都为0的时候,会先输入左子树,再输入右子树 2.此时的 ...

  2. Python爬虫(十)_正则表达式

    本篇将介绍python正则表达式,更多内容请参考:[python正则表达式] 什么是正则表达式 正则表达式,又称规则表达式,通常被用来检索.替换那些符合某个模式(规则)的文本. 正则表达式是对字符串操 ...

  3. 每天一个JavaScript实例-防止反复表单提交

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  4. Struts框架的国际化

    本文将通过一个详细的实例来展示Struts框架的国际化,使用的版本号是struts1.1. 案例:在一个页面上有一个下拉框,下拉框中有3个国家的语言选项,各自是"中文简体".&qu ...

  5. TCP/IP具体解释--UDP数据报中的IP分片

    1.UDP首部 2.UDP分片 在第二章,讲链路层是,提到过以太网.刨除数据帧帧头.最多传输的长度为1500.也就是说,假设一个ip数据报,长度大于1500,则须要分片. 分片方法: 在ip头中3位标 ...

  6. linux 安装tensorflow(gpu版本)

    一.安装cuda 具体安装过程见我的另一篇博客,ubuntu16.04下安装配置深度学习环境 二.安装tensorflow 1.具体安装过程官网其实写的比较详细,总结一下的话可以分为两种:安装rele ...

  7. 项目实战13—企业级虚拟化Virtualization-KVM技术

    项目实战系列,总架构图 http://www.cnblogs.com/along21/p/8000812.html KVM的介绍.准备工作和qemu-kvm 命令详解 1.介绍 (1)介绍 KVM:就 ...

  8. 在非controllers中获取httpServletRequest

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()) ...

  9. 自定义控件详解(七):drawText()

    比较基础的一个方法.即绘制文本 使用如下: Paint paint = new Paint(); paint.setColor(Color.RED); // 红色字体 paint.setStyle(P ...

  10. Android破解学习之路(四)——Android游戏 3D摩托飞车破解

    经过前面三期的破解,想必大家已经非常熟悉破解的流程,这一篇也算是练手项目,我们继续来练习吧 apk下载地址:链接: https://pan.baidu.com/s/1sl3b3R3 密码: 6666 ...