python 反射 元类 自定义类方法 day-24-day-25

反射

  什么是反射、
    通过字符串来操作类或者对象的属性
如何用
  hasattr
  getattr  
  setattr
  delattr



class People:
country='China'
def __init__(self,name):
self.name=name

def eat(self):
print('%s is eating' %self.name)

peo1=People('egon')


# print(hasattr(peo1,'eat')) #peo1.eat

# print(getattr(peo1,'eat')) #peo1.eat
# print(getattr(peo1,'xxxxx',None))

# setattr(peo1,'age',18) #peo1.age=18
# print(peo1.age)

# print(peo1.__dict__)
# delattr(peo1,'name') #del peo1.name
# print(peo1.__dict__)


class Ftp:
def __init__(self,ip,port):
self.ip=ip
self.port=port

def get(self):
print('GET function')

def put(self):
print('PUT function')

def run(self):
while True:
choice=input('>>>: ').strip()
# print(choice,type(choice))
# if hasattr(self,choice):
# method=getattr(self,choice)
# method()
# else:
# print('输入的命令不存在')

method=getattr(self,choice,None)
if method is None:
print('输入的命令不存在')
else:
method()

conn=Ftp('1.1.1.1',23)
conn.run()

 自定义内置方法来定制类的功能

__str__方法

class People:

  def __init__(self,name,age):

    self.name=name

    self.age=age

在对象被打印是,自动触发,应该在该方法内采集与对象有关的信息,然后凭接

凭接成字符串返回

  def __str__(self):
# # print('======>')
# return '<name:%s age:%s>' %(self.name,self.age)
# obj=People('egon',18)
# obj1=People('alex',18)
# print(obj) #obj.__str__()
# print(obj) #obj.__str__()
# print(obj) #obj.__str__()
# print(obj1) #obj1.__str__()


# d={'x':1} #d=dict({'x':1})
# print(d)

__del__析构方法

__del__会在对象被删除之前自动触发

class People:

  def __init__(self,name,age):

    self.name=name

    self.age=age

    self.f=open('file-name','rt',encoding='utf-8')

  def __del__(self):

    self.f.close()

obj=People('egon',18)

print('主')

什么是元类

  在python中一切街对象,那么我们用class关键字定义的类本身也是一个对象

负责产生该对象的类称之为元类,即元类可以简称为类的类

class Foo:#Foo=元类()

  pass

为何要用元类

  元类是负责产生类的,所以我们学习元类或者自定义元类的目的

  是为了控制类的产生的过程,还可以控制对象的产生过程

如何用元类

  元类是负责产生类的,所以我们学习元类或者自定义元类的目的

  是为控制类产生过程,还可以控制对象的产生过程


'''
#1、储备知识:内置函数exec的用法
# cmd="""
# x=1
# def func(self):
# pass
# """
# class_dic={}
# exec(cmd,{},class_dic)
#
# print(class_dic)


创建类的方法有两种

  大前提:如果说类也是对象的话,那么用class关键字去创建类的过程

也是一个实例化的过程,该实例化的目的是为了得到一个类,调用的是元类

方式一:用的默认元类是type

class People:#People=type()

  country='china'

  def __init__(self,name,age):

    self.name=name

    self.age=age

  def eat(self):

    print('%s is eating '%self.name)

print(type(People))


#2.1.1 创建类的3个要素:类名,基类,类的名称空间
class_name='People'
class_bases=(object,)
class_dic={}
class_body="""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)
"""
exec(class_body,{},class_dic)

# 准备好创建类的三要素
# print(class_name)
# print(class_bases)
# print(class_dic)

# People=type(类名,基类,类的名称空间)
# People1=type(class_name,class_bases,class_dic)
# print(People1)
# obj1=People1('egon',18)
# print(People)
# obj=People('egon',18)
#
# obj1.eat()
# obj.eat()

'''
#2.2 方式二:用的自定义的元类
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
print(self) #现在是People
print(class_name)
print(class_bases)
print(class_dic)
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能

# 分析用class自定义类的运行原理(而非元类的的运行原理):
#1、拿到一个字符串格式的类名class_name='People'
#2、拿到一个类的基类们class_bases=(obejct,)
#3、执行类体代码,拿到一个类的名称空间class_dic={...}
#4、调用People=type(class_name,class_bases,class_dic)
class People(object,metaclass=Mymeta): #People=Mymeta(类名,基类们,类的名称空间)
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)


# 应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程

class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0:
raise TypeError('类中必须有文档注释,并且文档注释不能为空')
if not class_name.istitle():
raise TypeError('类名首字母必须大写')
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能

class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....})
"""这是People类"""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)
'''


#3 储备知识:__call__
# class Foo:
# def __call__(self, *args, **kwargs):
# print(self)
# print(args)
# print(kwargs)
#
#
# obj=Foo()
#
# # 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法
# # 该方法会在调用对象时自动触发
# obj(1,2,3,x=1,y=2)


# 4、自定义元类来控制类的调用的过程,即类的实例化过程
class Mymeta(type):

def __call__(self, *args, **kwargs):
# print(self) # self是People
# print(args)
# print(kwargs)
# return 123

# 1、先造出一个People的空对象
obj=self.__new__(self)
# 2、为该对空对象初始化独有的属性
# print(args,kwargs)
self.__init__(obj,*args,**kwargs)

# 3、返回一个初始好的对象
return obj


class People(object,metaclass=Mymeta):
country='China'
def __init__(self,name,age):
self.name=name
self.age=age

def eat(self):
print('%s is eating' %self.name)

def __new__(cls, *args, **kwargs):
print(cls)
# cls.__new__(cls) # 错误
obj=super(People,cls).__new__(cls)
return obj

# 分析:调用Pepole的目的
#1、先造出一个People的空对象
#2、为该对空对象初始化独有的属性
# obj1=People('egon1',age=18)
# obj2=People('egon2',age=18)
# print(obj1)
# print(obj2)

obj=People('egon',age=18)
print(obj.__dict__)
print(obj.name)
obj.eat()
class Mymeta(type):
n=444
def __call__(self, *args, **kwargs):
obj = self.__new__(self) # self=Foo
# obj = object.__new__(self) # self=Foo
self.__init__(obj, *args, **kwargs)
return obj

class A(object):
n=333
# pass

class B(A):
n=222
# pass
class Foo(B,metaclass=Mymeta): # Foo=Mymeta(...)
n=111
def __init__(self, x, y):
self.x = x
self.y = y


print(Foo.n)
#查找顺序:
#1、先对象层:Foo->B->A->object
#2、然后元类层:Mymeta->type


# print(type(object))

# obj=Foo(1,2)
# print(obj.__dict__)








class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic):
#控制类Foo的创建
super(Mymeta,self).__init__(class_name,class_bases,class_dic)

def __call__(self, *args, **kwargs):
#控制Foo的调用过程,即Foo对象的产生过程
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
obj.__dict__={'_%s__%s' %(self.__name__,k):v for k,v in obj.__dict__.items()}

return obj

class Foo(object,metaclass=Mymeta): # Foo=Mymeta(...)
def __init__(self, name, age,sex):
self.name=name
self.age=age
self.sex=sex


obj=Foo('egon',18,'male')
print(obj.__dict__)
















1、什么是单例模式
单例模式:基于某种方法实例化多次得到实例是同一个
2、为何用单例模式
当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即同一个实例
3、如何用
'''

# 单例模式实现方式一:
# import settings
#
# class Mysql:
# __instacne=None
#
# def __init__(self,ip,port):
# self.ip=ip
# self.port=port
#
# @classmethod
# def from_conf(cls):
# if cls.__instacne is None:
# cls.__instacne=cls(settings.IP,settings.PORT)
# return cls.__instacne
# # obj=Mysql('1.1.1.10',3306)
#
# obj1=Mysql.from_conf()
# obj2=Mysql.from_conf()
# obj3=Mysql.from_conf()
#
# print(obj1)
# print(obj2)
# print(obj3)
#
# obj4=Mysql('10.10.10.11',3307)


# 单例模式实现方式二:
# import settings
# def singleton(cls):
# cls.__instance=cls(settings.IP,settings.PORT)
# def wrapper(*args,**kwargs):
# if len(args) == 0 and len(kwargs) == 0:
# return cls.__instance
# return cls(*args,**kwargs)
# return wrapper
#
# @singleton #Mysql=singleton(Mysql) #Mysql=wrapper
# class Mysql:
# def __init__(self,ip,port):
# self.ip=ip
# self.port=port
#
#
# obj1=Mysql() #wrapper()
# obj2=Mysql() #wrapper()
# obj3=Mysql() #wrapper()
# print(obj1 is obj2 is obj3)
# print(obj1)
# print(obj2)
# print(obj3)
# obj4=Mysql('1.1.1.4',3308)
# print(obj4)




# 单例模式实现方式三:
import settings

class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic): #self=Mysql
super(Mymeta,self).__init__(class_name,class_bases,class_dic )
self.__instance=self.__new__(self) #造出一个Mysql的对象
self.__init__(self.__instance,settings.IP,settings.PORT) #从配置文件中加载配置完成Mysql对象的初始化

# print(self.__instance)
# print(self.__instance.__dict__)

def __call__(self, *args, **kwargs): #self=Mysql
if len(args) == 0 and len(kwargs) == 0:
return self.__instance

obj=self.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj



class Mysql(object,metaclass=Mymeta): #Mysql=Mymeta(...)
def __init__(self,ip,port):
self.ip=ip
self.port=port


obj1=Mysql()
obj2=Mysql()
obj3=Mysql()
obj4=Mysql('10.10.10.11',3308)

print(obj1)
print(obj2)
print(obj3)
print(obj4)










上节课复习:
1、什么是元类
元类是我们自定义类的类,即我们用class定义的类本质
就是在实例化元类

class Foo: #Foo=元类('类名',(obejct),class_dic)
pass

obj=Foo()

2、为何用用元类+如何用?
2.1 控制class定义类的过程
class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic):
#控制逻辑
super().__init__(class_name,class_bases,class_dic)

class Foo(object,metaclass=Mymeta): #Foo=Mymeta('Foo',(object,),{'x':1,....})
x=1


2.2 控制对象(指的就是Foo的对象)的产生过程
class Mymeta(type):
def __call__(self,*args,**kwargs):
obj=self.__new__(self) #self=Foo
self.__init__(obj,*args,**kwargs)
return obj

class Foo(object,metaclass=Mymeta): #Foo=Mymeta(...)
def __init__(self,x,y):
self.x=x
self.y=y

obj=Foo(x=1,y=2)



今日内容:
1、单例模式的三种实现方式
2、异常处理













上节课复习:
1、封装
class Foo:
__n=111 #_Foo__n
def __init__(self,x):
self.__x=x #self._Foo__x

def func(self):
self.__x #self._Foo__x
Foo.__n #Foo._Foo__n

obj=Foo()
obj.__x
Foo.__n

Foo.__m=111
obj,__y=22


class Foo:
__x=111 #_Foo__x

class Bar(Foo):
__x=222 #_Bar__x

2、property
可以将类内的函数伪装成一个数据属性去访问

class Foo:
def __init__(self,x):
self.__x=x

#新的写法
@property
def x(self):
return self.__x

@x.setter
def x(self,val)
self.__x=val

@x.deleter
def x(self):
del self.__x


# 古老的写法
def get_x(self):
pass

def set_x(self,val):
pass

def del_x(self):
pass

x=property(get_x,set_x,del_x)
obj=Foo(10)
obj.x
obj.x=1
del obj.x


3、绑定方法与非绑定方法
@classmethod

@staticmethod



今日内容:
1、反射
hasattr
setattr
getattr
delattr

2、内置的方法
__str__
__del__

3、元类(*****)
用于实例化产生类的类称之为元类
__call__
__new__

单例模式

猜你喜欢

转载自www.cnblogs.com/yanxiatingyu/p/9314502.html