1 和面向对象相关的常用内置函数
1.1 issubclass
作用:
检查第一个参数是否是第二个参数的 子子孙孙类
案例:
1 class Base(object): 2 pass 3 4 class Foo(Base): 5 pass 6 7 class Bar(Foo): 8 pass 9 # 检查第一个参数是否是第二个参数的 子子孙孙类 10 print(issubclass(Bar,Base)) #True |
1.2 type
作用:
获取当前对象是由那个类创建
实例:
1 class Foo(object): 2 pass 3 4 obj = Foo() 5 6 print(obj,type(obj)) # 获取当前对象是由那个类创建。 7 if type(obj) == Foo: 8 print('obj是Foo类型') 9 10 答案: 11 # <__main__.Foo object at 0x0000014F613E83C8> <class '__main__.Foo'> 12 # obj是Foo类型 13 14 |
![]() 1 class Foo(object): 2 pass 3 4 class Bar(object): 5 pass 6 7 def func(*args): 8 foo_counter =0 9 bar_counter =0 10 for item in args: 11 if type(item) == Foo: 12 foo_counter += 1 13 elif type(item) == Bar: 14 bar_counter += 1 15 return foo_counter,bar_counter 16 17 # result = func(Foo(),Bar(),Foo()) 18 # print(result) 19 v1,v2 = func(Foo(),Bar(),Foo()) 20 print(v1,v2) #2 1 |
1.3 isinstance
作用:
检查第一个参数(对象)是否是第二个参数(类及父类)的实例
案例:
![]() 1 class Base(object): 2 pass 3 4 class Foo(Base): 5 pass 6 7 obj1 = Foo() 8 print(isinstance(obj1,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 #True 9 print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 #True 10 11 obj2 = Base() 12 print(isinstance(obj2,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 #False 13 print(isinstance(obj2,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 #True |
1.4 type与isinstance的区别
给你一个参数,判断对象是不是由某一个指定类? type --> type(obj) == Foo 给你一个参数,判断对象是不是由某一个指定类或其父类? isinstance --> instance(obj,Foo) |
形象一点:
type:只认她岳父岳母(具体)
isinstance:认她岳父岳母以及她的所有长辈
2 方法和函数的区别
2.1 介绍
称谓: 类,方法 外,函数 到底方法函数? 对象.xxx --> xxx就是方法 类.xxx --> xxx就是函数 xxx --> xxx就是函数 打印查看: function method
|
实例
![]() 1 class Foo(object): 2 3 def detail(self): 4 pass 5 6 @staticmethod 7 def ss(): 8 pass 9 def func(): 10 pass 11 12 obj = Foo() 13 print(obj.detail) #<bound method Foo.detail of <__main__.Foo object at 0x000001BBBAC38470>> 14 print(Foo.ss) #<function Foo.ss at 0x000001BBBAC39A60> 15 print(func) #<function func at 0x00000145E2659950> |
2.2 最科学的区分函数和方法
![]() 1 from types import MethodType,FunctionType 2 def check(arg): 3 ''' 4 检查arg是方法还是函数? 5 :param arg: 6 :return: 7 ''' 8 if isinstance(arg,MethodType): 9 print('这是一个方法') 10 elif isinstance(arg,FunctionType): 11 print('这是一个函数') 12 else: 13 print('不知道是什么') 14 15 def func(): 16 pass 17 18 class Foo(object): 19 def detail(self): 20 pass 21 @staticmethod 22 def xxx(): 23 pass 24 25 26 check(func) #这是一个函数 27 28 obj = Foo() 29 check(obj.detail) #这是一个方法 30 check(obj.xxx) #这是一个函数 |
2.3 特点(与调用者有关系,调用的方式不同,就不同)
![]() 1 class Foo(object): 2 3 def f1(self): 4 pass 5 6 def f2(self): 7 pass 8 9 def f3(self): 10 pass 11 12 13 obj = Foo() 14 print(Foo.f1) # 把f1当做函数,类的调用方式不能直接传参 #<function Foo.f1 at 0x00000159EFB698C8> 15 16 obj = Foo() 17 print(obj.f1) # 把f1当做方法,自动传self值 #<bound method Foo.f1 of <__main__.Foo object at 0x00000159EFB689E8>> 18 总结:类. 是函数 19 对象. 是方法 |
3 如何判断一个参数一个类还是对象呢?
![]() 1 #判断一个对象是不是类 2 class Foo: 3 pass 4 5 print(type(Foo)==type) #True #返回True表示是类 6 7 |
4 callable() 如何判断一个对象是否能被调用呢?
4.1 什么可以被调用?
- 类()
- 对象()
- 函数()
- 方法()
4.2 callable() 那么如何判断一个对象是否能被调用?
![]() 1 # callable()判断一个对象是否可以被调用 2 def func(): 3 pass 4 5 class Foo(object): 6 def __call__(self, *args, **kwargs): 7 pass 8 def func(self): 9 pass 10 obj = Foo() 11 12 13 print(callable(func)) #True 14 print(callable(Foo)) #True 15 print(callable(obj)) #True 16 print(callable(obj.func)) #True |
5 为什么要有方法与函数的划分呢
下面是个人的浅见:
方法可以自动传参,这就是区别,但是这只不过是省了一个步骤而已,为何要多此一举的在区分函数和方法呢?在这里你应该把这个self参数当作一个封装的包裹,里面的东西不仅仅是一个东西,这样的话,就有必要区分函数和方法
6 反射
所谓反射,就是一种映射关系。
下面我们由一种需求来引出反射的必要性
v = getattr(obj,"func") # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员
6.1 需求
6.1.1 之前的方式
![]() 1 while True: 2 print(""" 3 系统支持的函数有: 4 1. f1 5 2. f2 6 3. f3 7 4. f4 8 5. f5 9 """) 10 val = int(input("请输入要执行的函数:")) 11 12 if val == 1: 13 pass 14 elif val == 2: 15 pass 16 elif val == 3: 17 pass 18 elif val == 4: 19 pass 20 elif val == 5: 21 pass |
如上面的方式,我们需要用到if ... elif ... elif ... else ... 。但这种方式对于判断大量数据的时候就有些不好了,下面看反射的方式
6.1.2 反射的方式(在模块中的应用)
![]() 1 ##handler.py 2 3 f0 = 9 4 5 6 7 def f1(): 8 9 print('F1') 10 11 12 13 def f2(): 14 15 print('F2') 16 17 18 19 def f3(): 20 21 print('F3') 22 23 24 25 def f4(): 26 27 print('F4') 28 29 30 31 def f5(): 32 33 print('F5')
|
![]() 1 from types import FunctionType 2 import handler 3 4 while True: 5 print(""" 6 系统支持的函数有: 7 1. f1 8 2. f2 9 3. f3 10 4. f4 11 5. f5 12 """) 13 val = input("请输入要执行的函数:") # val = "f1" 14 # 错误 15 # handler.val() #用这种方式代替if ...elif....elif...else,但尝试失败。因为val本质是一个字符串并不是一个内存地址 16 17 if hasattr(handler, val): # 判断handler模块是否有val变量的内容所代表的函数 18 func_or_val = getattr(handler, val) # 根据字符串为参数,去handler模块中寻找与之同名的成员。 19 if isinstance(func_or_val, FunctionType): 20 func_or_val() # 如果是方法就执行这个方法,否则打印 21 else: 22 print(func_or_val) 23 else: 24 print('handler中不存在输入的属性名') 25 26 27 28 注意:从上面可以看是怎么体现反射的,所谓反射就是映射关系。通过getattr来判断映射项中是否有与之对应的。 |
案例1:在面向对象中的应用
![]() 1 class Foo(object): 2 3 country = "中国" 4 5 def func(self): 6 pass 7 8 9 v = getattr(Foo,'func') # Foo.func # 根据字符串为参数,去类中寻找与之同名的成员。 10 print(v) #<function Foo.func at 0x00000153C64198C8> 11 12 obj = Foo() 13 v = getattr(obj,"func") # obj.func # 根据字符串为参数,去对象中寻找与之同名的成员。 14 print(v) #<bound method Foo.func of <__main__.Foo object at 0x00000153C64184E0>> |
案例2:
![]() 1 class Foo(object): 2 3 def __init__(self,a1): 4 self.a1 = a1 5 self.a2 = None 6 7 obj = Foo(1) 8 9 v1 = getattr(obj,'a1') 10 print(v1) #1 11 12 setattr(obj,'a2',2) #更改变量 13 14 v2 = getattr(obj,'a2') 15 print(v2) #2 |
案例3:
![]() 1 class Account(object): 2 3 func_list = ['login', 'logout', 'register'] 4 5 6 7 def login(self): 8 9 """ 10 11 登录 12 13 :return: 14 15 """ 16 17 print('登录111') 18 19 20 21 def logout(self): 22 23 """ 24 25 注销 26 27 :return: 28 29 """ 30 31 print('注销111') 32 33 34 35 def register(self): 36 37 """ 38 39 注册 40 41 :return: 42 43 """ 44 45 print('注册111') 46 47 48 49 def run(self): 50 51 """ 52 53 主代码 54 55 :return: 56 57 """ 58 59 print(""" 60 61 请输入要执行的功能: 62 63 1. 登录 64 65 2. 注销 66 67 3. 注册 68 69 """) 70 71 72 73 choice = int(input('请输入要执行的序号:')) 74 75 func_name = Account.func_list[choice-1] 76 77 78 79 # func = getattr(Account,func_name) # Account.login 80 81 # func(self) 82 83 84 85 func = getattr(self, func_name) # self.login 86 87 func() 88 89 90 91 obj1 = Account() 92 93 obj1.run() 94 95 96 97 obj2 = Account() 98 99 obj2.run() |