一.对特殊成员的补充
1.__str__
如果一个类中定义了__str__方法,那么在打印对象是,默认输出该方法的返回值
# __str__ class Foo: 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__
表示类的描述信息
# __doc__ class Foo: """ 娃哈哈 """ def __int__(self): pass def func(self): pass def __str__(self): return 'F1' obj = Foo() print(obj.__doc__) 结果: 娃哈哈
3.__dict __
类或对象中的所有成员
类的普通字段属于对象;类中的静态字段和方法等属于类
# __dict__ class Foo: def __init__(self,name,age): self.name = name self.age = age def func(self): pass obj = Foo('剑豪',23) obj1 = Foo('剑圣',34) print(obj.__dict__) # 获取对象obj的成员 print(obj1.__dict__) # 获取对象obj1的成员 结果: {'name': '剑豪', 'age': 23} {'name': '剑圣', 'age': 34}
4.__iter__
用于迭代器,之所以列表,字典,元组可以进行for循环,是因为类型内部定义了__iter__
# __iter__ # l1是list类的一个对象,可迭代对象 l1 = [11,22,33,44] # l2是list类的一个对象,可迭代对象 l2 = [1,2,3,4] class Foo: def __init__(self,name,age): self.name = name self.age = age def func(self): pass def __iter__(self): return iter([11,22,33,44,55,66,7]) # 或 # yield 123 # yield 456 # yield 789 # obj1是Foo类的一个对象,可迭代对象 """ 如果想要把不可迭代对象 -> 可迭代对象 1. 在类中定义__iter__方法 2. iter内部返回一个迭代器(生成器也是一种特殊迭代器) """ obj = Foo('盖伦',23) for item in obj: print(item) 结果: 11 22 33 44 55 66 7
5.突然想起一道题
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 结果: [33] [33,33]
6.嘿嘿,还有一题
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 结果: [33] [33,33]
7.跟前两题差不多,好好看啊
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() s2 = StarkConfig() result1 = s1.get_list_display() print(result1) # 33 result2 = s2.get_list_display() print(result2) # 33 结果: [33] [33]
8.给前几题来个总结:
(1).注意创建的对象
(2).注意上面的类的静态变量
二.issubclass/type/isinstance/
1.issubclass
检查第一个参数是不是第二个参数的子子孙孙类
# issubclass class Foo(object): pass class Base(Foo): pass class Bar(Base): pass print(issubclass(Bar,Foo)) # 检查第一个参数是否是第二个参数的 子子孙孙类 结果: True
2.type
获取当前对象是由哪个类创建的
# type class Foo(object): pass obj = Foo() print(type(obj)) # 获取当前对象是由那个类创建。 if type(obj) == Foo: print('obj是Foo类型') 结果: <class '__main__.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) 结果: (2,1)
3.isinstance
检查第一个参数(对象)是否是第二个参数的(类或父亲)
# isinstance class Foo(object): pass class Base(Foo): pass obj = Base() print(isinstance(obj,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 print(isinstance(obj,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 obj1 = Foo() print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 print(isinstance(obj1,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。 结果: True True False True
三.用科学的方法判断是函数还是方法
1.调用:from types import MethodType,FunctionType
from types import MethodType,FunctionType def func(arg): """ 检查arg是方法还是函数 :param arg: :return: """ if isinstance(arg,MethodType): print('arg是一个方法') elif isinstance(arg,FunctionType): print('arg是一个函数') else: print('谁知道是啥玩意')
class Foo(object): def f1(self): pass def f2(self): pass def f3(self): pass # obj = Foo() # print(obj.f1) # print(obj.f2) obj = Foo() Foo.f1(obj) # 把f1当做函数 obj = Foo() obj.f1() # 把f1当做方法,自动传self值
class Foo(object): def f1(self): pass def f2(self): pass def f3(self): pass list_display = [f1,f2] def __init__(self): pass for item in Foo.list_display: item(123)
class Foo(object): def f1(self): pass def f2(self): pass def f3(self): pass list_display = [f1,f2] obj = Foo() Foo.list_display.append(obj.f3) for item in Foo.list_display: print(item)
2.总结:
称谓:
类.方法
外.函数
到底是方法还是函数?
对象.XXX --> XXX就是方法
类.XXX --> XXX就是函数
XXX --> XXX就是函数
打印查看:
function --> 函数
method -->方法
四.反射
根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员
1.记住
getattr # 根据字符串的形式,去对象中找成员。
hasattr # 根据字符串的形式,去判断对象中是否有成员。
setattr # 根据字符串的形式,动态的设置一个成员(内存)
delattr # 根据字符串的形式,动态的删除一个成员(内存)
2.示例一(模块和包)
from types import FunctionType import handler while True: print(""" 系统支持的函数有: 0. f0 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中不存在输入的属性名') # 正确方式 """ if val == 'f1': handler.f1() elif val == 'f2': handler.f2() elif val == 'f3': handler.f3() elif val == 'f4': handler.f4() elif val == 'f5': handler.f5() """
3.示例二(类)
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()
4.反射补充
""" getattr # 根据字符串的形式,去对象中找成员。 hasattr # 根据字符串的形式,去判断对象中是否有成员。 setattr # 根据字符串的形式,去判断对象动态的设置一个成员(内存) delattr # 根据字符串的形式,去判断对象动态的设置一个成员(内存) """ import xx # getattr v1 = getattr(xx,'x1') v2 = getattr(xx,'f1') v2('杨森') # hasattr v3 = hasattr(xx,'x1') v4 = hasattr(xx,'f1') v4 = hasattr(xx,'f1') v5 = hasattr(xx,'xxxxxxx') print(v3,v4,v5) # setattr setattr(xx,'x2',999) v6 = getattr(xx,'x2') print(v6) setattr(xx,'f2',lambda x:x+1) v7 = getattr(xx,'f2') v8 = v7(1) print(v8) # delattr delattr(xx,'x1') v9 = getattr(xx,'x1') print(v9)
""" getattr # 根据字符串的形式,去对象中找成员。 hasattr # 根据字符串的形式,去判断对象中是否有成员。 setattr # 根据字符串的形式,去判断对象动态的设置一个成员(内存) delattr # 根据字符串的形式,去判断对象动态的设置一个成员(内存) """ class Foo(object): def __init__(self,a1): self.a1 = a1 self.a2 = None obj = Foo(1) v1 = getattr(obj,'a1') print(v1) setattr(obj,'a2',2) v2 = getattr(obj,'a2') print(v2)
五. 小知识点补充
callable:可以检查一个对象是否是可以调用的
你见过什么后面可以加()?
>>>类()
>>>对象()
>>>函数()
>>>方法()
以上所有都可以被调用.
def func(): pass class Foo(object): def __call__(self, *args, **kwargs): pass def func(self): pass obj = Foo() print(callable(func)) print(callable(Foo)) print(callable(obj)) print(callable(obj.func))