给对象添加属性和给类添加属性
都是直接 对象名.名字 = xxx 类名.名字 = xxx
给类添加方法
实例方法
这样添加run方法的时候他不会把p1这个对象扔进去,所以就缺少一个参数,导致程序会蹦。
所以我们会使用types.MethondType(函数名,对象名)就相当将函数名绑到这个对象上去。
class Person(object):
def __init__(self,newName):
self.name = newName
def run(self):
print("---%s正在吃---"%self.name)
p1 = Person("w")
p1.eat = types.MethondType(eat, p1)
p1.eat()
'''
输出结果:
---p1正在跑---
'''
p1.eat = types.MethodType(eat, p1)
这句话的意思就是我们去调eat函数时,就会把p1当做第一个参数往eat函数中传。那为什么会写p1.eat呢?这个只是相当于我们将来在调用函数的时候,我们用什么方法去调用它呢?就相当于一个返回值,有一个返回值在去调eat这个时候它就会把p1传进去了,p1.eat就相当于等号后面的返回值。此时eat函数就相当于:
def eat(p1):
p1.name
那谁来调用这个函数呢?就是我们在等号前面的p1.eat,此时p1.eat就指向我们的eat函数,就是它帮我们找到了eat函数。如果没有它我们调用不了eat函数。
那么为什么我们一般要写 对象,函数名 来作为这个返回值呢?而不是直接写xxx,因为我们写的types.MethodType(eat, p1) 就相当于把eat函数放入p1对象中去了,如果我们到时候需要去用p1.name,我们就可以直接使用p1.eat( )调用,就不需要重新去设置。
一般情况下,我们都是绑定的是什么就直接命名为什么。
静态方法
就直接用 类名.xx = 函数名 但xx一般与函数名一致。
这里就不能 p1.xx = 函数名 原因是不可将静态方法添加到对象上面, 静态方法属于类,应该添加到类上面。
类方法
类方法也跟实例方法一样
总结
你如果要给实例方法添加一个方法那么你就要用types.MethodType 因为这个是给对象添加方法。
而如果你要给类方法和实例方法添加方法那么你可以直接添加。因为这两种是直接给类添加方法而不是给对象添加方法。
slots
动态语⾔:可以在运⾏的过程中,修改代码
静态语⾔:编译时已经确定好代码,运⾏过程中不能修改
如果我们想要动态语言中限制实例的属性怎么办?
为了达到限制的⽬的,Python允许在定义class的时候,定义⼀个特殊的 __slots__变量,来限制该class实例能添加的属性:
>>> class Person(object):
__slots__ = ("name", "age")
>>> P = Person()
>>> P.name = "⽼王"
>>> P.age = 20
>>> P.score = 100
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
AttributeError: Person instance has no attribute 'score'
>>>
注意:
使⽤__slots__要注意,__slots__定义的属性仅对当前类实例起作⽤,对继承的⼦类是不起作⽤的。
In[1]: class test(Person):
...: pass
...:
In[2]: t = test()
In[3]: t.score = 100