Python随笔12

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
原文地址:https://www.cnblogs.com/bigbigtong/p/10259749.html