主要内容:
- 1. isinstance, type, issubclass
- 2. 方法和函数的区别
- 3. 反射(重点)
1. isinstance, type, issubclass
(1) issubclass(xxx,yyy) 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar, Foo)) #True print(issubclass(Foo, Bar)) #False print(issubclass(Bar, Base)) #True
(2) type
type(obj) 表示查看obj是由哪个类创建的
class Foo: pass obj = Foo() print(obj, type(obj)) # 查看obj的类
判断xxx是否是xxx数据类型的
class Boy: pass class Girl: pass # 统计传进来的男生和女生分别有多少 def func(*args): b = 0 g = 0 for obj in args: if type(obj) == Boy: b += 1 elif type(obj) == Girl: g += 1 return b, g ret = func(Boy(), Girl(), Girl(), Girl(), Boy(), Boy(), Girl()) print(ret) # (3, 4)
在进行计算的时,先判断好要计算的数据类型必须是int或者float. 这样的计算才有意义
def add(a, b): if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float): return a + b else: print("我要报错")
(3) isinstance(xxx,yyy): 判断xxx是yyy类型的数据. 但是isinstance没有type那么精准
class Base: pass class Foo(Base): pass class Bar(Foo): pass print(isinstance(Foo(), Foo)) # True print(isinstance(Foo(), Base)) # True print(isinstance(Foo(), Bar)) # False
isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)
2. 方法和函数的区别
2.1 在类外边定义的函数一定是函数
def func(): print("你猜猜看") print(func) #<function func at 0x000002819F1B6048>
2.2 写在类中的函数
class Foo: # 实例方法: 对象.方法 方法 类名.方法 函数 def func(self): print("这里是什么呢!") obj = Foo() print(obj.func) #绑定的方法<bound method Foo.func of <__main__.Foo object at 0x00000217422E7978>>
Foo.func(obj) print(Foo.func) #类名直接调用就是方法 <function Foo.func at 0x000002BCB0528A60>
注: 如果通过对象方法,那么self 它会自动帮你传递, 如果使用类名来调用,self就不会帮你传递
2.3 类中的类方法,静态方法
class Foo: @staticmethod def static_method(): pass @classmethod # 都是方法 def class_method(cls): # 类对象的内容 pass @property # 神马都不是. 变量 def age(self): return 10 f = Foo() # print(f.static_method) #<function Foo.static_method at 0x000001ACF90D8A60> # print(Foo.static_method) #<function Foo.static_method at 0x0000012304688A60> # print(f.class_method) #<bound method Foo.class_method of <class '__main__.Foo'>> # print(Foo.class_method) #<bound method Foo.class_method of <class '__main__.Foo'>> print(f.age) #10 print (Foo.age) # <property object at 0x000002B3197FB7C8>
2.4 通过 types中的FunctionType和MethodType可以区分当前内容是方法还是函数,
注: 判断是方法还是函数
from types import MethodType,FunctionType def check(arg): ''' 判断arg是函数则打印1,arg是方法则打印2 :param arg ''' if isinstance(arg,MethodType): print(2) elif isinstance(arg,FunctionType): print(1) else: print('不认识') def func(): pass class Foo(object): def display(self): pass check(func) #1 check(Foo.display) #1 check(Foo().display) #2
2.5 练习
class RoleConfig(object): def f1(self,arg): print('f1',arg) def f2(self,arg): print('f2',arg) list_display =[f1,f2] # obj = RoleConfig() for item in RoleConfig.list_display: item(RoleConfig()
class RoleConfig(object): def f1(self, arg): print('f1', arg) def f2(self, arg): print('f2', arg) def f3(self, arg): print('f3', arg)
#静态字段 list_display = [f1, f2] def get_list_display(self): self.list_display.insert(0, RoleConfig.f3) return self.list_display obj1 = RoleConfig() for item in obj1.get_list_display(): item(obj1, 2) obj2 = RoleConfig() for item in obj2.get_list_display(): item(obj2, 6)
class RoleConfig(object): def f1(self, arg): print('f1', arg) def f2(self, arg): print('f2', arg) def f3(self, arg): print('f3', arg) list_display = [f1, f2] def get_list_display(self): v = [] v.extend(self.list_display) v.insert(0, RoleConfig.f3) return v obj1 = RoleConfig() for item in obj1.get_list_display(): item(obj1, 2) obj2 = RoleConfig() for item in obj2.get_list_display(): item(obj2, 6)
小结:
- 类方法. 不论任何情况, 都是方法.
- 静态方法, 不论任何情况. 都是函数
- 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.
3.反射
3.1 引入
一个需求, 说, 有个大牛, 写一堆特别牛B的代码. 然后放在一个py文件里(模块),这时, 你想用这个大牛写的东西,但是呢. 你首先得知道大牛写的这些代码都是干什么用的. 那就需要你把大牛写的每一个函数跑一下. 摘⼀摘自己想用的内容. 来咱们模拟 这样的需求,首先, 大牛给出一个模块.
def chi(): print ("大牛一次吃一桶") def he(): print ("大牛一顿喝100杯水") def la(): print ("大牛不用拉") def sleep(): print("大牛一睡睡一年") name = "大牛"
import master while 1 : print('''大牛写了很多东西 chi he la sleep ''') val = input("请输入你要测试的功能")
#判读 master这个py 文件中是否有你想要的的功能 if hasattr(master,val):
#获取这个功能 (从xxx对象中或者模块中找到xxx(字符串)功能,变量) attr = getattr(master,val)
#判断这个东西是否可以被调用 if callable(attr): attr() else: print(attr) else: print("没有这个功能")
上面有两个函数:一个是getattr(),hasattr().
- getattr()用来获取信息.
- hasattr()用来判断xxx中是否包含了xxx功能,.
3.2 反射的概述
(1)反射的定义(什么是反射机制):
- 反射就是通过字符串的形式,导入模块;
- 通过字符串的形式,去模块寻找指定函数,并执行。
- 利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动
3.3 反射的使用
3.3.1面向对象中的反射
(1)hasattr (xxx, ooo) (判断xxx中是含有ooo)
class Movie(object): def __init__(self,name): self.name = name def release(self): print('%s正在放映'%self.name) movie =Movie('大话西游')
#hasattr 返回的是True / False print(hasattr(movie,'name')) #True 存在name这个属性 print(hasattr(movie,'release')) #True 存在release这个方法 print(hasattr(movie,'place')) #False 不存在产地place这个属性
(2)getattr
class Movie(object): language = '国语' def __init__(self,name): self.name = name def release(self): print('%s正在放映'%self.name) movie =Movie('大话西游') #从类中获取属性 attr = getattr(Movie,'language') print(attr) #国语 #获取对象的属性 attr1 = getattr(movie,'name') print(attr1) #大话西游(获取到的是name的内存地址) #获取对象可执行的方法 attr2 = getattr(movie,'release') attr2() # 大话西游正在放映 print(attr2) #<bound method Movie.release of <__main__.Movie object at 0x00000215EDF585F8>>
注;
关于 getattr(object,'xxxx' 'not find') 第三个参数意思是当从object对象中获取不到xxx时候返回 第三个参数
(3)setattr()
class Movie(object): language = '国语' def __init__(self,name): self.name = name def release(self): print('%s正在放映'%self.name) movie =Movie('大话西游') setattr(movie,'name','少林足球') #可以动态的给对象设置属性 print(movie.name) #少林足球 setattr(movie,'place','内地') #可以给对象设置属性和值 print(movie.place) # 内地
(4)delattr()
class Movie(object): language = '国语' def __init__(self,name): self.name = name def release(self): print('%s正在放映'%self.name) movie =Movie('大话西游') #少林足球 setattr(movie,'place','内地') #可以给对象设置属性和值 print(movie.place) # 内地 delattr(movie,'place') print(movie.place) #已删除
反射共有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成员删除掉
注意, 以上操作都是在内存中进行的. 并不会影响你的源代码