1.1 动态语言
在运行时代码可以根据某些条件改变自身结构,可以在运行时引进新的函数、对象、甚至代码,可以删除已有的函数等其他结构上的变化
常见的动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang
1.2 动态类型语言
在运行期间检查数据类型的语言
数据类型不是在编译阶段决定的,而是把类型绑定延后到了运行阶段
常见的动态类型语言:Python、Ruby、Erlang、JavaScript、swift、PHP、Perl
1.3 强类型语言
一旦一个变量被指定了某个数据类型,如果不经过强制类型转换,那么它就永远是这个数据类型
常见的强类型语言:Java、C#、Python、Object-C、Ruby
Python是动态语言,动态类型语言,也是强类型语言。所以Python可以在运行时改变自身结构,动态添加/删除属性和方法。
types.MethodType(function, instance),function为需要进行绑定的函数名,instance是需要进行绑定的实例。
MethodType可以将instance所给的值,作为第一个参数传递给function函数中,返回值是一个method的对象实例。
import types
def testMethodType(temp,num):
return temp+num
print(types.MethodType(testMethodType,100))
a = types.MethodType(testMethodType,100)
print(a(3))
首先需要明白的一点就是,由于python是动态的语言,也就是说变量的作用是可以直接改变的。
如:
类的实例进行动态添加属性
其次需要明白的一点就是,由于python是动态的语言,也就是说所有的不是在类定义的时候就创建好的属性与方法的修改,都是进行的了动态的扩展与绑定,只不过是恰巧起了一个相同的名字而已。
如:
class A():
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
a = A()
a.__num = 300
print(a.__num)
输出结果为
300
本来对于a这个实例来说,__num应该是一个私有的属性,是不允许直接进行访问的,但是为什么可以直接访问呢?
原因是因为python是动态语言,在执行a.__num的时候是进行了动态的属性扩展,此时已经是一个与私有属性同名的扩展属性了,不再是私有的。
类的实例进行动态添加实例方法
由于python的动态性,那么应该可以进行动态的方法的添加,但是在添加实例方法的时候需要注意的是,被绑定的方法,必须严格按照写在这个类本身之内的格式进行书写,而且在类的实例方法中,有一个默认第一个传递的值为这个实例本身(通常为self,但不一定),而在直接进行绑定的时候是不会主动进行传递这个类的实例的,也就是会绑定不成功,此时需要借助types.MethodType()函数进行协助。
class A():
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
def testmethod(self):
print("----testmethod-----")
a = A()
a.testmethod = testmethod
a.testmethod()
结果为报错:
此时采用types.MethodType的协助
import types
class A():
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
def testmethod(self):
print("----testmethod-----")
a = A()
a.testmethod = types.MethodType(testmethod,a)
a.testmethod()
此时结果为:
----testmethod-----
类进行动态添加属性
给类直接动态添加属性的方法与原理跟给类的实例进行动态添加属性的方法与原理是一样的,只不过是作用于是不同的。一个的作用域是此时的实例,一个作用域是此时的整个类。
如:
class A():
__testnum = 50
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
A.__testnum = 100
print(A.__testnum)
输出为:
100
给一个类动态的添加一个classmethod方法或者staticmethod方法
由于Python的动态语言性质,所以也可以给一个类动态的添加一个classmethod方法与staticmethod方法。
classmethod动态添加
动态的添加classmethod函数时要求,被添加的函数必须完全按照写在类本身当中的书写要求进行书写,包括使用@classmethod进行装饰,虽然classmethod函数有一个默认第一个传递的值是此类的本身(通常为cls,但不一定),但是在进行动态绑定的时候会自动进行传递,则不需要进行辅助函数的使用,直接绑定就好。
如:
@classmethod
def printClass(cls):
print("--------classmethod")
class A():
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
A.printClass = printClass
A.printClass()
输出结果为:
--------classmethod
如果在调用的时候进行再次传参,则直接报错。
staticmethod动态添加
动态的添加staticmethod函数时要求,被添加的函数必须完全按照写在类本身当中的书写要求进行书写,包括使用@staticmethod进行装饰,由于staticmethod的使用规则无其他限制,则无需进行辅助函数的帮助,直接绑定即可。
如:
@staticmethod
def printStatic(num):
print("--------classmethod----%d"%num)
class A():
def __init__(self):
self.__num = 200
def num1(self):
return self.__num
def num2(self,num):
if num < 999:
self.__num = num
num = property(num1,num2)
A.printStatic = printStatic
A.printStatic(1)
输出结果为:
--------classmethod----
1
在python中动态绑定的属性与方法,存活期都是在此时这个类与实例存活的存在运用的时候才存在的,一旦类与实例不存在了,则动态绑定也不存在了。
在实例中绑定的属性与方法,作用域是此时的这个实例,别的实例并没有。在整个类中绑定的属性与方法,作用域是这个类,别的类没有,但是这个类的实例有