Python是动态语言,可以在运行时改变其结构,比如给类添加属性、方法,引入代码,已有的函数被删除或者其它结构上的改变。
给实例绑定属性和方法:
定义一个空类Person,用到代码桩(Pass,暂时没有逻辑代码,用Pass占位,代码执行到这里,继续向下执行),给它的实例绑定属性和方法。
class Person(object): pass #类的实例 s = Person() #给空类的实例绑定属性 s.name = "Jerry" print(s.name) #定义一个方法 def set_age(self,age): self.age = age from types import MethodType # Python3中,用types.MethodType(methodName,instance),可以把一个方法绑定到实例对象上,同样也可以把方法绑定到类中 #返回值是methodName对应的方法anotherRef,这个anthodRef可以调用methodName对应的方法,把instance当作self s.set_age = MethodType(set_age,s) s.set_age(25) print(s.age)
输出的结果为:
Jerry
25
可以看到,原本一个空类,现在我们给它的实例绑定了属性name和set_age()方法。那么在另外一个实例中,是否可以也有这些属性和方法呢?
s2 = Person() print(hasattr(s2,"name"))
我们用hasattr()可以查看实例s2是否有name属性,返回结果为False,说明s2没有name属性。再来看是否有set_age()方法。
s2.set_age(30) print(s2.age)
结果报这样一个错,AttributeError: 'Person' object has no attribute 'set_age'。说明set_age()方法也不能用在s2这个实例上。
事实上,给类的实例绑定的属性和方法是不能适用于其他实例的。
给空类绑定属性和方法:
class Person(object): pass def set_age(self,age): self.age = age #类名.属性=值 给类绑定属性 Person.name = "www" Person.set_age =set_age p1 = Person() p1.set_age(18) print(p1.age) p2 = Person() p2.set_age(30) print(p2.age) print(p1.name) #查看类中是否有这个name属性 print(hasattr(Person,"name"))
结果为:
18
30
www
True
可以看到,成功的给类绑定了属性和方法,在类的实例中可以直接调用绑定的方法,也可以访问绑定的属性。同样也可以用TypeMethod()方法给类动态的绑定方法
class Person(object): pass def set_age(self,age): self.age = age from types import MethodType #实例化对象和类都是对象,所以types.MethodType()方法同样也实用于方法 # 但是通过这种方法给类绑定方法,set_age就是给类设置属性了,所以以最后一个为准 Person.set_age = MethodType(set_age,Person) p1 = Person() p2 = Person() p1.set_age(22) p2.set_age(88) print(p1.age) #输出为88 print(p2.age)
结果为:
88 88
可以看到,成功的给类绑定了方法,但是set_age()方法也给类设置了属性,所以每一个类的实例都会更改age属性的值,以最后一个为准。
__slots__,限制类的属性,意思就是如果在一个类中存在__slots__ = (arg1,arg2)那么就意味着这个类的实例只能有arg1和arg2两个属性,不能用实例动态的绑定属性。值对类的实例有效,对于子类的实例不受此限制。
class Person(object): __slots__ = ("name","age") #限制这个类的实例只能有name和age两个属性 p = Person() p.name = "Tom" p.age = 8 print(p.name,p.age) p.weight = 20 print(p.weight)
结果为:
Tom 8 Traceback (most recent call last): File "D:/PythonDemo/动态语言-__slots__.py", line 11, in <module> p.weight = 20 AttributeError: 'Person' object has no attribute 'weight'
可以看到,类的实例不能再绑定其他属性了
但是子类就不受此限制
class A(Person): pass a1 = A() a2 = A() a1.name = "Tom" a1.age = 10 a1.weight = 11 a2.name = "Jerry" a2.age = 5 a2.weight = 2 print(a1.name,a1.age,a1.weight) print(a2.name,a2.age,a2.weight)
结果为:
Tom 10 11
Jerry 5 2