一、三个内置函数
1、issubclass(a, b) 判断a类是否是b类的子类
class Foo:
passclass Zi(Foo):
passclass Sun(Zi):
passprint(issubclass(Zi,Foo)) #Trueprint(issubclass(Zi,Sun)) # Falseissubclass
1 class Foo: 2 pass 3 4 class Zi(Foo): 5 pass 6 7 class Sun(Zi): 8 pass 9 print(issubclass(Zi,Foo)) #True10 print(issubclass(Zi,Sun)) # False
2、type(对象) 返回该对象的数据类型,精确识别(即不向上兼容)
class Animal:
passclass Cat(Animal):
passclass BosiCat(Cat):
passc = Cat()
b = BosiCat()print(type(c)) #<class '__main__.Cat'> 会准确说出c是一种Cat,不会说c是一种Animaltype
1 class Animal: 2 pass 3 4 class Cat(Animal): 5 pass 6 7 class BosiCat(Cat): 8 pass 9 10 c = Cat() 11 b = BosiCat()12 print(type(c)) #会准确说出c是一种Cat,不会说c是一种Animal
3、isinstance(对象,类) 判断xx对象是否是xxx类 (向上兼容)
class Animal:
passclass Cat(Animal):
passclass BosiCat(Cat):
passc = Cat()
b = BosiCat()print(isinstance(c , Cat)) #判断c 是否是一种Cat
print(isinstance(c,Animal)) #判断c 是否是一种Animalprint(isinstance(c,BosiCat))结果:TrueTrueFalseisinstace
class Animal: passclass Cat(Animal): passclass BosiCat(Cat): passc = Cat()b = BosiCat()print(isinstance(c , Cat)) #判断c 是否是一种Catprint(isinstance(c,Animal)) #判断c 是否是一种Animalprint(isinstance(c,BosiCat)) 结果:TrueTrueFalse
二、判断函数与方法
python官方定义:
函数function —— A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body.
方法method —— A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self).
从定义看,函数就相当于一个数学公式,它不与其他东西相互关联,传递相应的参数就能用。而方法是,定义在类内部的函数,并且这个函数和类或类的实例对象有某种关联,访问时会自动传递一个参数作为第一参数。
简单来说:
函数没和类或对象进行绑定;
方法和类或对象有绑定
# 区分函数和方法:
def func():
passprint(func) # <function func at 0x10646ee18> 函数class Foo:def chi(self):
print("我是吃")f = Foo()print(f.chi) # <bound method Foo.chi of <__main__.Foo object at0x10f688550>> 方法函数和方法
1 def func(): 2 pass 3 print(func) #函数 4 class Foo: 5 6 def chi(self): 7 print("我是吃") 8 f = Foo() 9 print(f.chi) # > 方法
class Foo:
def chi(self): print("我是吃") @staticmethod def static_method(): pass @classmethod def class_method(cls): passf = Foo()
print(f.chi) # <bound method Foo.chi of <__main__.Foo object at
0x10f688550>>print(Foo.chi) # <function Foo.chi at 0x10e24a488>
print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620>print(Foo.class_method) # bound method Foo.class_method of <class'__main__.Foo'>>print(f.static_method) # <function Foo.static_method at 0x10e1c0620>
print(f.class_method) #<bound method Foo.class_method of <class'__main__.Foo'>>函数和方法
1 class Foo: 2 def chi(self): 3 print("我是吃") 4 @staticmethod 5 def static_method(): 6 pass 7 @classmethod 8 def class_method(cls): 9 pass10 11 f = Foo()12 13 print(f.chi) #>15 16 print(Foo.chi) # 17 print(Foo.static_method) # 18 print(Foo.class_method) # bound method Foo.class_method of >20 21 print(f.static_method) # 22 print(f.class_method) # >
结论:
1. 类方法. 不论任何情况, 都是方法.
2. 静态方法, 不论任何情况. 都是函数
3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.
#官方判断方法:
通过types模块引入MethodType FunctionType 来判断
from types import FunctionType, MethodType
class Car:
def run(self): # 实例方法 print("我是车, 我会跑")@staticmethod
def cul(): print("我会计算")@classmethod
def jump(cls): print("我会jump")c = Car()
实例方法:
# 1. 用对象.方法 方法# 2. 类名.方法 函数c = Car() print(isinstance(c.run, FunctionType)) # False print(isinstance(Car.run, FunctionType)) # True print(isinstance(c.run, MethodType)) # True print(isinstance(Car.run, MethodType)) # False# 静态方法 都是函数
print(isinstance(c.cul, FunctionType)) # True print(isinstance(Car.cul, FunctionType)) # True print(isinstance(c.cul, MethodType)) # False print(isinstance(Car.cul, MethodType)) # False# 类方法都是方法
print(isinstance(c.jump, FunctionType)) # Falseprint(isinstance(Car.jump, FunctionType)) # Falseprint(isinstance(c.jump, MethodType)) # Trueprint(isinstance(Car.jump, MethodType)) # True判断
1 from types import FunctionType, MethodType 2 3 class Car: 4 def run(self): # 实例方法 5 print("我是车, 我会跑") 6 7 @staticmethod 8 def cul(): 9 print("我会计算")10 11 @classmethod12 def jump(cls):13 print("我会jump")14 15 c = Car()16 17 实例方法:18 # 1. 用对象.方法 方法19 # 2. 类名.方法 函数20 c = Car()21 print(isinstance(c.run, FunctionType)) # False22 print(isinstance(Car.run, FunctionType)) # True23 print(isinstance(c.run, MethodType)) # True24 print(isinstance(Car.run, MethodType)) # False25 26 # 静态方法 都是函数27 print(isinstance(c.cul, FunctionType)) # True28 print(isinstance(Car.cul, FunctionType)) # True29 print(isinstance(c.cul, MethodType)) # False30 print(isinstance(Car.cul, MethodType)) # False31 32 # 类方法都是方法33 print(isinstance(c.jump, FunctionType)) # False34 print(isinstance(Car.jump, FunctionType)) # False35 print(isinstance(c.jump, MethodType)) # True36 print(isinstance(Car.jump, MethodType)) # True
三、反射(重点)
关于反射, 其实一共有4个函数:
1. hasattr(obj, str) 判断obj中是否包含str成员
2. getattr(obj,str) 从obj中获取str成员
3. setattr(obj, str, value) 把obj中的str成员设置成value 这里的value可以是值, 也可以是函数或者方法
4. delattr(obj, str) 把obj中的str成员删除掉
注意:
obj可以是模块,类,实例对象
以上操作都是在内存中进行的, 并不会影响你的源代码,但是在同一个py文件中,你通过反射修改了类,是会影响到其他对象的。
1 #反射用到的四个函数,常用的是hasattr 和getattr 2 # setattr(a,b,c) a是要操作的对象,b是操作对象中的成员字符串形式,c是修改的值 3 # getattr(a,b) 有返回值,返回值形式a.b a是要操作的对象,b是操作对象中的成员字符串形式 4 #delattr(a,b) a是要操作的对象,b是操作对象中的成员字符串形式 5 #hasatter(a,b) a是要操作的对象,b是操作对象中的成员字符串形式 6 7 class Car: 8 9 def __init__(self,color,pai,price):10 self.color = color11 self.pai = pai12 self.price= price13 14 def fly(self):15 print('我的车会飞')16 17 c = Car('blue','丰田','18888')18 f = getattr(Car,"fly") #操作对象是类,返回值相当于Car.fly19 print(f) #这里是函数,没有和类绑定,所以需要下面手动传值20 f(c) # f是函数,没有和类绑定,所以需要手动传值Car.fly(c) ,它是等价于c.fly()的21 22 #delattr(Car,"fly") #操作的是类,把类中fly方法删除了23 #c.fly() #报错,没有fly24 25 c2 =Car("yellow","bmw",20000)26 27 def fly():28 print("通过对象c修改fly方法")29 30 setattr(c,"fly",fly) #并没有改变类中的内容,相当于在当前对象中创建了一个fly方法,一个对象是不可能有修改类的权限的31 c.fly() #通过对象c修改fly方法32 c2.fly() #我的车会飞33 c3 = Car("blue","奔驰",88888)34 c3.fly() #我的车会飞35 setattr(Car,'fly',lambda self:print('通过类名,修改fly方法')) #通过类名修改fly方法36 c.fly() #通过对象c修改fly方法37 c2.fly() #通过类名,修改fly方法38 c3.fly() #通过类名,修改fly方法39 c4 = Car("red","悍马",66666)40 c4.fly() #通过类名,修改fly方法