Python:Day25 成员修饰符、特殊成员、反射、单例

时间:2023-03-09 01:13:56
Python:Day25  成员修饰符、特殊成员、反射、单例

一、成员修饰符

  共有成员

  私有成员,__字段名,__方法

    - 无法直接访问,只能间接访问

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 = '' #静态字段
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 = ''
self.__gene = '' 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('')
return 2222 obj = foo()
print(obj,type(obj)) #<__main__.foo object at 0x000000000065E3C8> <class '__main__.foo'>
r = int(obj) #int一个对象,自动执行对象中的__int__方法,并将返回值赋值给int对象
print(r) #

  __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()

Python:Day25  成员修饰符、特殊成员、反射、单例

异常处理

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) # 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('')

单例模式:

单例,使用同一个实例(对象)

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>