这几天看了一本书,感觉写挺好的,作者有一小节是说用了python的动态特性,不同于C语言中的静态类,能够实现非常出乎意料的功能。这里面用到了动态绑定,一查才发现,这背后的知识更加丰富。。
先贴一张截图吧。。
这就是我看的那本书的那一小节的介绍。代码的话可以参考:https://download.csdn.net/download/edward_zcl/12001634
其中关于多重继承,类/实例的数据成员(可随意动态绑定),成员函数,方法(静态,私有),属性,装饰器,迭代器,构造函数,元类等等,可变对象与不可变对象,numpy与list,默认构造函数,函数定义,作用域等等,以及最后本节要重点介绍的动态绑定,这些知识都有使用,必须融会贯通才能真正读懂全部代码。
关于动态绑定我先看了这篇博客:
https://www.cnblogs.com/luoheng23/p/10989435.html
文中最后的一段代码:
class A:
def test_hello(self):
print("hello")
def test_world(self):
print("world")
def main():
s = A()
# 提前绑定
f = s.test_hello
# 改变方法
A.test_hello = test_world
f()
# 动态绑定
s.test_hello()
if __name__ == "__main__":
main()
没问题,运行。
from types import MethodType
class A:
def test_hello(self):
print("hello")
def test_world(self):
print("world")
def main():
s = A()
# 提前绑定
f = s.test_hello
# 改变方法
A.test_hello = test_world
f()
# 动态绑定
s.test_hello()
s1=A()
s1.test_hello()
if __name__ == "__main__":
main()
如果改成上面这样,运行也没问题。
from types import MethodType
class A:
def test_hello(self):
print("hello")
def test_world(self):
print("world")
def main():
s = A()
# 提前绑定
f = s.test_hello
# 改变方法
s.test_hello = test_world
f()
# 动态绑定
s.test_hello()
s1=A()
s1.test_hello()
if __name__ == "__main__":
main()
但改成这样就会出现问题了。
于是,后来我又看这篇博客:
https://www.cnblogs.com/lnlvinso/p/8999834.html
这篇博客里面详细介绍了from types import MethodType
中的type
与MethodType
以及__slots__
等关键字或者包的用法,自带的包,功能还是很强的。这种形式可以说其实很常见,只是这种功能不常见哈哈。。
文中这段代码:
class Student(object):
pass
stu1 = Student();
stu1.name = 'Tom'
print(stu1.name)
print(dir(stu1))
def set_age(self, age):
self.age = age
set_age(stu1, 20)
print(stu1.age)
print(dir(stu1))
#并没有绑定方法到实例上
Student.set_age = set_age
stu1.set_age(33)
print(stu1.age)
运行没问题,无关python版本,编译器,编辑器,或者函数名,以及数据成员,self等东西的事。
仔细观察才发现,人家博客开头:
原来Python是动态语言,在类定义了之后,还可以动态地绑定属性和方法。下面先来看怎么给类的实例动态地绑定属性和方法。
这特么是个针对类的实例的用法,所以说还是那套,类的方法可以直接动态绑定,而类的实例方法的成员函数动态绑定需要这样借助type
包才可以,否则报错。不过它们的数据成员都可以任意随意绑定,但是有作用域的区别。另外,既然是动态绑定,是打算属于类或者是实例的方法,需要的self
参数还是需要的,尽管你可能不用它,甚至可以换个名字。。
虽然上面确实把python中的动态绑定讲清楚了,但是可最上面的那个图片好像关系不大。只能说上面那是一种更加广泛的动态绑定:
- 作者使用的
VGGTest
实例使用了多重继承的默认的VGGNet
的构造函数,但是其他的类没有构造函数,所以是不是需要确实不写,或者写了需要什么歌优先级顺序呢? - 作者使用未定义的
CnnTrainInterface
的forward
函数,但是不报错,这个才是动态绑定的核心,因为多重继承,可能已经完成了这样的动态绑定,作者实例化的时候,以及综合融合多重继承时候的各个类的方法,重新进行了整合,self
的作用凸显,直接深入,也可以直接跳出,可以任意调用其他函数,游走于各大类之间,动态绑定,VGGNet
类的forward
函数才是真正被使用的,指令是由VGGTest
执行搜索调用的。
不过作者自己也写了,这种方法省了一些事,但是会带来一些不必要的麻烦,可读性减弱,容易产生误导,并且产生一些类或者实例或者函数间的耦合,不利于维护与调试,最好改写的方法还是写明,思路清晰,各模块独立。
不过,python设计的初衷,就是要求活学活用,融会贯通,一些都是对象,动态编程是它一直追求的。
更多参考:
https://www.cnblogs.com/luoheng23/p/11050347.html
https://www.jb51.net/article/131624.htm
https://www.cnblogs.com/qikeyishu/p/10740659.html
https://www.cnblogs.com/moonpool/p/11333541.html
https://blog.csdn.net/qq_35075164/article/details/80918072
https://blog.csdn.net/qq_35075164/article/details/80918072
https://blog.csdn.net/weixin_30268071/article/details/98457164
https://blog.csdn.net/qq_17592003/article/details/82704968