--在python中,一切皆对象,类也可以理解为“对象”,而type元类又称作构建类,python中大多数内置的类(包括object)以及自己定义的类,都是油type元类创造的
print(type('abc')) print(type(True)) print(type(100)) print(type([1, 2, 3])) print(type({'name': '太白金星'})) print(type((1,2,3))) print(type(object)) class A: pass print(isinstance(object,type)) print(isinstance(A, type)) print(isinstance(str,type))
-
而type类与object类之间的关系比较独特:object是type类的实例,而type类是object类的子类,这就属于鸡生蛋蛋生鸡的关系。
反射
--python面向对象中的反射:通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)
--一切皆对象,类本身也是一个对象
四个可以实现自省的函数---hasattr getattr setattr delattr
-
对实例对象的反射
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #检测是否含有某属性 print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #获取属性 n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','不存在啊')) #报错 #设置属性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #删除属性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,则报错 print(obj.__dict__)
-
对类的反射
class Foo(object): staticField = "old boy" def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' @staticmethod def bar(): return 'bar' print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')
-
对当前模块(本文件)的反射
import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
-
对其他模块(其他文件)的反射
# test.py 文件 def test(): print('from the test') # index.py 文件 import test as obj print(hasattr(obj,'test')) getattr(obj,'test')()
反射的应用:以前写登录注册等,需要定义一个字典进行匹配,如果使用反射,会使代码更灵活简单
class User: def login(self): print('欢迎来到登录页面') def register(self): print('欢迎来到注册页面') def save(self): print('欢迎来到存储页面') user = User() while 1: choose = input('>>>').strip() if hasattr(user,choose): func = getattr(user,choose) # 类---方法 func() else: print('输入错误。。。。')
函数和方法区分
1. 函数和方法的区分
-
通过打印函数(方法)名确定
def func(): print('func...') print(func) # <function func at 0x00000260A2E690D0> class A: def func(self): print('in A func') print(A.func) # <function A.func at 0x0000026E65AE9C80> obj = A() print(obj.func) #<bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>
-
通过types模块验证
from types import FunctionType from types import MethodType def func(): pass class A: def func(self): pass obj = A() print(isinstance(func,FunctionType)) # True 直接函数 print(isinstance(A.func,FunctionType)) # True 类调用 print(isinstance(obj.func,FunctionType)) # False 对象访问方法 print(isinstance(obj.func,MethodType)) # True
-
静态方法是函数
class A: @staticmethod def func(self): pass obj = A() # 静态方法其实是函数 print(isinstance(A.func2,FunctionType)) # True print(isinstance(obj.func2,FunctionType)) # True
2. 函数与方法的区别
-
函数与方法最显著的区别就是是否为隐形传参,隐形传参的就是方法
双下方法
--双下方法是特殊方法,他是解释器提供的,__方法名__的具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法
--调用:不同的双下方法,调用的方式也不同
-
__len__
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) # __dict__可查看对象中的属性(字典格式),len之后可以获取对象中字典的个数 a = A() print(len(a))
-
__hash__
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
-
__str__:如果一个类中定义了这个双下方法,那么在打印对象是,默认输出该方法的返回值
class A: def __init__(self): pass def __str__(self): return 'lucky' a = A() print(a) print('%s' % a)
-
__repr__
:一个类中定义了__repr__
,那么在repr(对象)时,默认输出该方法的返回值
class A: def __init__(self): pass def __str__(self): return 'lucky' a = A() print(repr(a)) print('%r'%a)
-
__call__
对象后面加(),触发执行
构造方法__new__
的执行是由创建对象触发的,即:对象 = 类名();而__call__
方法的执行是由对象后+()触发的,即:对象() 或者 类()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
-
__eq__
:执行双等判断的时候触发
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
-
__del__
:析构方法,当对象在内存中被释放是,自动触发执行
注:这个方法一般不需要定义,因为python解释器会自动执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
-
__new__
:在__init__
之前调用
注:__new__
至少要有一个参数cls,代表要实例化的类,这个参数python解释器自动提供
__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以return父类__new__
出来的实例,或者直接是object的__new__
出来的实例。
__init__
有一个参数self,这个就是__new__
返回的实例,__init__
在__new__
的基础上可以完成一些其他初始化的动作,__init__
不需要返回值
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a = A() print(a.x) __item__ class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)