面向对象中特殊方法的补充、isinstance/issubclass/type、方法和函数、反射
一、面向对象中特殊方法的补充
1.__str__ 能将对象名改成你想要的字符串,但是类型还是类
class Foo(object): def __init__(self): pass def func(self): pass def __str__(self): return "f1" obj = Foo() print(obj,type(obj)) # f1 <class '__main__.Foo'>
2.__doc__ 能将类的注释文档显示出来
class Foo(object): ''' asdqwe ''' def __init__(self): pass def func(self): pass obj = Foo() print(obj.__doc__) # asdqwe
3.__dict__ 能将对象中封装的数据以字典的形式输出
class Foo(object): def __init__(self,name,age): self.name = name self.age = age def func(self): pass obj1 = Foo("a1",14) obj2 = Foo("a2",15) print(obj1.__dict__) #{'name': 'a1', 'age': 14} print(obj2.__dict__) #{'name': 'a2', 'age': 15}
4.__iter__
如果想要把不可迭代对象转变成可迭代对象:
1.在类中定义__iter__方法
2.iter内部返回一个迭代器(生成器也是一种特殊迭代器)
class Foo(object): def __init__(self,name,age): self.name = name self.age = age def func(self): pass def __iter__(self): return iter([11,22,33,44]) obj = Foo("a1",13) for el in obj: print(el) # 11 # 22 # 33 # 44
几个实例:
class StarkConfig(object): list_display = [] def get_list_display(self): self.list_display.insert(0,33) return self.list_display class RoleConfig(StarkConfig): list_display = [11,22] s1 = StarkConfig() result1 = s1.get_list_display() print(result1) # [33] result2 = s1.get_list_display() print(result2) # [33,33]
class StarkConfig(object): def __init__(self): self.list_display = [] def get_list_display(self): self.list_display.insert(0, 33) return self.list_display class RoleConfig(StarkConfig): list_display = [11, 22] s1 = StarkConfig() result1 = s1.get_list_display() print(result1) # [33] result2 = s1.get_list_display() print(result2) # [33, 33]
二、sinstance/issubclass/type三种方法
1.issubclass #检查第一个参数是否是第二个参数的子类或子孙类
class Base(object): pass class Foo(Base): pass class Bar(Foo): pass print(issubclass(Bar,Base)) print(issubclass(Foo,Base)) # True # True
2.type #获取当前对象是由哪个类创建的
class Foo(object): pass obj = Foo() print(obj, type(obj)) # 获取当前对象是由那个类创建。 if type(obj) == Foo: print('obj是Foo类型') # obj是Foo类型
练习题
class Foo(object): pass class Bar(object): pass def func(*args): foo_counter = 0 bar_counter = 0 for item in args: if type(item) == Foo: foo_counter += 1 elif type(item) == Bar: bar_counter += 1 return foo_counter, bar_counter #函数返回值为多个值以元组的形式返回 result = func(Foo(),Bar(),Foo()) print(result) v1, v2 = func(Foo(), Bar(), Foo()) #解构 print(v1, v2)
3.isinstance 判断第一个参数(对象),是否是第二个参数(类及父类)的实例
class Bar(object): pass class Base(Bar): pass class Foo(Base): pass obj1 = Foo() print(isinstance(obj1,Foo)) print(isinstance(obj1,Base)) print(isinstance(obj1,Bar)) # True # True # True
**type:判断对象是不是由某一个指定类 type(obj)==Foo
**isinstance:判断对象是不是由某一个指定类或其父类 isinstance(obj,Foo)
三、判断是方法还是函数
称谓:类,方法
外,函数
对象.xxx---->xxx就是方法
类.xxx ----->xxx就是函数
xxx ------>xxx就是函数
代码判断:
from types import FunctionType,MethodType def check(arg): """ 检查arg是函数还是方法 :param arg: :return: """ if isinstance(arg,FunctionType): print("arg是一个函数") elif isinstance(arg,MethodType): print("arg是一个方法") else: print("arg什么都不是") class Foo(): def f1(self): pass obj = Foo() check(obj.f1) #arg是一个方法 check(Foo.f1) #arg是一个函数
四、反射
getattr 根据字符串的形式,去对象中找成员 v = getattr(obj,"func")
hasattr 根据字符串的形式,去判断对象中是否有成员
setattr 根据字符串的形式,动态的设置一个成员(内存)
delattr 根据字符串的形式,动态的删除一个成员(内存)
from types import FunctionType import handler while True: print(""" 系统支持的函数有: 1. f1 2. f2 3. f3 4. f4 5. f5 """) val = input("请输入要执行的函数:") # val = "f1" # 错误 # handler.val() if hasattr(handler, val): func_or_val = getattr(handler, val) # 根据字符串为参数,去模块中寻找与之同名的成员。 if isinstance(func_or_val, FunctionType): func_or_val() else: print(func_or_val) else: print('handler中不存在输入的属性名')
class Account(object): func_list = ['login', 'logout', 'register'] def login(self): """ 登录 :return: """ print('登录111') def logout(self): """ 注销 :return: """ print('注销111') def register(self): """ 注册 :return: """ print('注册111') def run(self): """ 主代码 :return: """ print(""" 请输入要执行的功能: 1. 登录 2. 注销 3. 注册 """) choice = int(input('请输入要执行的序号:')) func_name = Account.func_list[choice - 1] # func = getattr(Account,func_name) # Account.login # func(self) func = getattr(self, func_name) # self.login func() obj1 = Account() obj1.run() obj2 = Account() obj2.run()
callable 判断是否能被调用