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