一、成员修饰符
共有成员
私有成员,__字段名,__方法
- 无法直接访问,只能间接访问
class Foo: def __init__(self,name,age): self.name = name self.__age = age #字段名前加双下划线就成私有成员了,外部无法直接访问 def show(self): #如果想访问的话需要定义一个公有成员,然后返回私有私有字段。 return self.__age obj = Foo('alex',18) print(obj.name) print(obj.__age) #外部无法直接访问,AttributeError: 'Foo' object has no attribute '__age' print(obj.show()) #通过定义的公有方法,可以间接访问
公有字段私有化
class Foo: __v = '123' #静态字段 def __init__(self): pass def show(self): return Foo.__v #前面必须要加Foo print(Foo.__v) #静态字段私有之后也是无法通过外部访问的 obj = Foo() print(obj.show())
继承中的私有字段:
class F(): def __init__(self): self.ge = '123' self.__gene = '234' class S(F): def __init__(self,name): self.name = name self.__age = 18 super(S,self).__init__() #想要使用父亲字段,必须要执行父类Init def show(self): print(self.name) print(self.__age) print(self.ge) #必须要在init中同时执行父类,不然此代码报错:AttributeError: 'S' object has no attribute 'ge' print(self.__gene) #继承的时候父亲中的私有字段不继承,如果想访问,要在父类中写一个公有方法间接访问 obj = S('alex') obj.show() #AttributeError: 'S' object has no attribute '_S__gene'
二、特殊成员
__init__ 类()自动执行
__call__ 对象() 类()()自动执行
class foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('aaa') foo()() #对象加括号自动执行__call__方法
__int__ int(对象)
class foo: def __init__(self): pass def __int__(self): print('1111') return 2222 obj = foo() print(obj,type(obj)) #<__main__.foo object at 0x000000000065E3C8> <class '__main__.foo'> r = int(obj) #int一个对象,自动执行对象中的__int__方法,并将返回值赋值给int对象 print(r) #2222
__str__ str(对象)
class foo: def __init__(self): pass def __str__(self): return 'alex' obj = foo() print(obj,type(obj)) #数据类型为<class '__main__.foo'> i = str(obj) #str一个对象,自动执行对象中的__str__方法 print(i) #alex
class foo: def __init__(self,n,a): #TypeError: object() takes no parameters,如果出现这个错误,一般是init写成了int self.name = n self.age = a def __str__(self): return '%s - %s'%(self.name,self.age) obj = foo('alex',18) print(obj) #print(str(obj)) str(obj)运行对象中的__str__方法,并获取其返回值
__add__
__del__
class foo: def __init__(self,n,a): self.name = n self.age = a def __add__(self, other): #self = obj1,other = obj2 return 'xxxoooo' def __del__(self): print('析构方法') #对象被销毁时,自动执行 obj1 = foo('alex',18) obj2 = foo('eric',66) r = obj1 + obj2 #两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当做参数传入 print(r,type(r))
__dict__ #将对象中封装的所有内容以字典的形式返回
class foo: def __init__(self,n,a): self.name = n self.age = a self.gender = 'male' obj = foo('alex',18) d = obj.__dict__ print(d) #{'gender': 'male', 'name': 'alex', 'age': 18} ret = foo.__dict__ #不仅可以返回对象的,也可以返回类中的成员,包括类的注释 print(ret)
__getitem__ #切片(sliceo类型)或者索引
__setitem__
__delitem__
class foo: def __init__(self,name,age): self.name = name self.age = age def __getitem__(self, item): return item+10 #因为这是获取数值,所以有返回值,下面两个没必要有返回值,因为也没地方接收了 def __setitem__(self, key, value): #key其实就是索引 print(key,value) def __delitem__(self, key): print(key) li = foo('alex',18) r = li[8] #自动执行li对象的类中的__getitem__方法,8当作参数传递给item print(r) li[100] = "asdjk" #这种对象带[]的形式,将自动执行__setitem__方法,key为中括号中值,value为等号后面值 # 这个方法没必要有返回值,因为这已经是个等式了,有返回值也没地接收了 del li[999] #这种形式和类中的__delitem__这个方法是对应的,执行此命令,将执行__delitem__方法 #只要前面几个的语法这样写,就对应执行上面的函数,也只是对应关系,具体执行什么操作和表面意思一点关系都没有
__iter__
class Foo: def __iter__(self): return iter([11,22,33]) obj = Foo() for i in obj: print(i) # 如果对象中有__iter__方法,那么该对象就是可迭代对象。 # 可迭代对象.__iter__返回的是一个迭代器。 # for循环的时候,如果循环的对象是可迭代对象,那么先执行对象的__iter__,然后针对return的迭代器进行迭代。 # 如果循环的对象是迭代器,那么就直接进行迭代。 # 迭代的本质其实就是执行迭代器的next方法
metaclass元类
在python中一切皆对象,对象是对象,类也是对象,类是type的对象。
class Foo: def func(self): print(123) # ============================================================================= def func(self): print("hello world!") Foo = type("QQQ",(object,),{"func":func}) #声明一个类,类中有一个成员func,成员信息可以用__dict__查看 # 上面两种写法是一样的 obj = Foo() print(Foo.__dict__) obj.func()
异常处理
try: # 代码块,逻辑 inp = input("请输入:") i = int(inp) except Exception as e: # e是Exception的对象,对象中封装了错误信息 # 上述代码块出错,自动执行当前代码块的内容 print(e) i = 1
Exception是大BOSS,包含所有异常,如果想捕捉某一类型的异常可以用具体异常类型。
try: int("22w") except IndexError as e: print(e) except ValueError as e: print("value_error:",e) except Exception as e: print("Exception",e) else: print("没错的时候执行这块,有错时不执行") finally: print("无论是否错误都执行")
反射:
- getattr
-setattr
-hasattr
-delattr
通过字符串的形式操作对象中的成员
class foo: def __init__(self,name,age): self.name = name self.age = age def show(self): print('this is the test') obj = foo('alex',18) r = getattr(obj,'name') #有返回值,返回值为对应字段的值 print(r) #alex r1 = getattr(obj,'show') #引种形式获取成员,括号后面的参数必须是字符串 r1() #执行show方法,得到结果:this is the test,说明getattr不仅可以获得字段,也可以获得方法。 setattr(obj,'score',88) #没有返回值,返回值为None print(obj.score) #88 r2 = hasattr(obj,'gender') #有返回值,返回值为布尔值 print(r2) #False delattr(obj,'score') print(obj.score) #AttributeError: 'foo' object has no attribute 'score'
#类也是对象,所以也可以对类使用上述函数 class foo: country = 'china' def show(self): print('this is the test') r = getattr(foo,'country') #同样可以获得里面的字段,因为类是type的对象,从这块可以看出,其实country和self.name一样,都是封装在对象里的内容 print(r) #china r1= hasattr(foo,'show') # print(r1) #True #为什么是ture?由此可以看出getattr获取的是包含在对象内部的内容。 # 那为什么之前对象可以获得类中的内容?因为对象中有类对象指针,所以类中的成员也是对象中的一部分
#在python中一切皆对象,所以模块也是对象,对模块也可以操作 import model1 r1 = getattr(model1,'s') print(r1) setattr(model1,'tel',88888) #虽然设置了,可以获取到值,但这些现在只是存在内存中,并未存在文件中 print(getattr(model1,'tel')) r2 = getattr(model1,'func') #获取模块中的函数 r2() r3 = getattr(model1,'cls') #获取模块中的类 obj = r3('alex',18) #创建对象 print(obj.name) #获取类中的name字段
反射小练习:仿WEB业面点击获得相应信息
class foo: def f1(self): return '首页' def f2(self): return '新闻' def f3(self): return '精华' inp = input('please input your URL>>>:') obj = foo() #因为方法中需要有self,所以要创建对象,如果不想创建对象,有两种方法,一是用静态方法,这样就不用传self了,另外一个是引入模块,在定义函数,这样也不用传参数 if hasattr(obj,inp): func = getattr(obj,inp) #这里用Foo也可以取到方法,但是执行的时候需要self,解决方法如上 result = func() print(result) else: print('404')
单例模式:
单例,使用同一个实例(对象)
class foo: __v = None #这个字段是静态字段,而且是私有字段 @classmethod #此处为类方法,这样的话,下面的方法的cls就不用传参了,python会自动传,此处也可以用静态方法,这样下面的参数就需要自己传了 def get_instance(cls): #此处的cls为类 if cls.__v: return cls.__v else: cls.__v = foo() #给__v赋值,前面必须要加cls,就像给self.name赋值一样 return cls.__v #return的值也要是cls.__v obj = foo.get_instance() #因为上面用的是类方法,所以这块不用传入参数类,如果为静态方法,那么此处括号内要加foo才行 obj1 = foo.get_instance() obj2 = foo.get_instance() print(obj) #<__main__.foo object at 0x00000000009B70B8> print(obj1) #<__main__.foo object at 0x00000000009B70B8> print(obj2) #<__main__.foo object at 0x00000000009B70B8>
第二次写单例:
class Foo: __v = None @classmethod # 这块用类方法好一些,因为在方法里面用到类了,用静态方法也行,只不过就要写成Foo.__v def get_instance(cls): if not cls.__v: cls.__v = Foo() return cls.__v obj1 = Foo.get_instance() print(obj1) # <__main__.Foo object at 0x0000000000426C18> obj2 = Foo.get_instance() print(obj2) # <__main__.Foo object at 0x0000000000426C18>