# 什么是元类:
# 源自于一句话:在python中,一切节对象,而对象都是由类实例化得到的
# class OldBoyTeacher:
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
#
# def score(self):
# print('%s is scoring'%self.name)
#
# tea1=OldBoyTeacher('egon',18,'male')
# print(type(tea1)) # <class '__main__.OldBoyTeacher'>
# print(type(OldBoyTeacher)) # <class 'type'>
# 对象tea1是调用OldBoyTeacher类得到的,如果说一切皆对象,那么OldBoyTeacher也是一个对象,只要是对象
# 都是调用一个类实例化得到的,即OldBoyTeacher=元类(....),内置的元类是type
"""
关系:
1调用元类————》自定义的类
2 调用自定义的类————》自定义的对象
#
class 关键字创建自定义类的底层的工作原理,分四步
1 先拿到类名:OldBoyTeacher
2 在拿到类的基类们:(object,)
3 然后拿到类的名称空间:
(执行类体代码,将产生的名字,放到类的名称空间也就是一个字典里,补充exec)
4 调用元类实例化得到的自定义的类:OldBoyTeacher=type('OldBoyTeacher',(object,),{....})
"""
# class OldBoyTeacher: #OldBoyTeacher=type(...)
# school='oldboy'
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
#
# def score(self):
# print('%s is scoring' % self.name)
# print(OldBoyTeacher) #<class '__main__.OldBoyTeacher'>
# 自定义类的三个关键组成部分:
# 1 类名
# 2 类的基类们
# 3 类的名称空间
# 不依赖class关键字创建一个自定义类
# 1 拿到类名
# class_name='OldBoyTeacher'
# 2 拿到类的基类们:(object,)
# class_base=(object,)
# 3 拿到类的名称空间
# class_dic={}
# class_body='''
# school = 'Oldboy'
#
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
#
# def score(self):
# print('%s is scoring' %self.name)
# '''
# #字符串 全局名称空间 局部名称空间
# exec(class_body,{},class_dic)
# #循环字符串里面的内容变成字典形式的添加到局部名称空间中
# print(class_dic)
# # {'school': 'Oldboy', '__init__': <function __init__ at 0x00000000004FC268>, 'score': <function score at 0x00000000027C97B8>}
#
# # 4 调用type得到自定义的类
# OldBoyTeacher=type(class_name,class_base,class_dic)
# print(OldBoyTeacher) #<class '__main__.OldBoyTeacher'>
# print(OldBoyTeacher.school) # Oldboy
# print(OldBoyTeacher.score) #<function score at 0x0000000001E59840>
#
# tea1=OldBoyTeacher('egon',18,'male')
# print(tea1.__dict__)
# # {'name': 'egon', 'age': 18, 'sex': 'male'}
'''
模板
class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就只是一个普通的类
def __init__(self,class_name,class_bases,class_dic):
print(self) #<class '__main__.OldboyTeacher'>
print(class_name) #OldboyTeacher
print(class_bases) #(<class 'object'>,)
print(class_dic) #{'__module__': '__main__', '__qualname__': 'OldboyTeacher', 'school': 'Oldboy', '__init__': <function OldboyTeacher.__init__ at 0x00000000021B9730>, 'score': <function OldboyTeacher.score at 0x00000000021B97B8>}
class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
school = 'Oldboy'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name)
'''
"""
# 控制类的产生
# 1 类名必须用驼峰体
# 2 类体必须有文档注释,且文档注释不能为空
class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就只是一个普通的类
def __init__(self,class_name,class_bases,class_dic):
if class_name.islower():
raise TypeError('类名必须使用驼峰体')
doc=class_dic.get('__doc__')
if doc is None or len(doc)==0 or len(doc.strip('\n '))==0:
raise TypeError('类体必须有文档注释,且文档注释不能为空')
# pass
class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
school = 'Oldboy'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name)
print(OldboyTeacher.__dict__)
# {'__module__': '__main__', 'school': 'Oldboy', '__init__': <function OldboyTeacher.__init__ at 0x00000000027D9730>, 'score': <function OldboyTeacher.score at 0x00000000027D97B8>, '__dict__': <attribute '__dict__' of 'OldboyTeacher' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyTeacher' objects>, '__doc__': None}
"""
# class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
# pass
#
# class OldboyTeacher(object): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
# school = 'Oldboy'
#
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
#
# def score(self):
# print('%s is scoring' %self.name)
#
# def __call__(self, *args, **kwargs):
# print(self) #<__main__.OldboyTeacher object at 0x00000000021E1668>
#
# print(args) #(1, 2)
#
# print(kwargs) #{'a': 1, 'b': 2}
# tea1=OldboyTeacher('egon',18,'male')
# tea1(1,2,a=1,b=2)
"""
总结:对象之所以可以调用,是因为对象的类中有一个函数__call__
推导:如果一切皆对象,那么OldboyTeacher也是一个对象,该对象之所以可以调用,肯定是这个对象的类中也定义了一个函数__call__
"""
'''
实例化OldboyTeacher,或者说调用OldboyTeacehr
1先产生一个空对象
2 执行__init__方法,完成对象的初始属性操作
3 返回初始化好的那个对象
推导:调用OldboyTeacher(..)就是在调用OldboyTeacher的类中的__call__ 那么在该__call__中就需要最上述三件事
'''
# 自定义元类来控制类的调用(类的实例化过程)
# class Mymeta(type):#但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
# def __call__(self, *args, **kwargs):
# # 1 先产生一个空对象
# tea_obj=self.__new__(self) #tea_obj是OldboyTeacher这个类的对象
#
# # 2 执行__init__方法,完成对象的初始属性操作
# # 这是用到了属性查找
# self.__init__(tea_obj, *args, **kwargs)
# print(tea_obj.__dict__)
# # {'name': 'egon', 'age': 18, 'sex': 'male'}
#
# # tea_obj.__dict__={('_%s__%s'%(self.__name__,k)):v for k,v in tea_obj.__dict__.items()}
# #可以对外界隐藏属性
#
# # 3 返回初始化好的那个对象
# return tea_obj
#
# class OldboyTeacher(object,metaclass=Mymeta):#OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
# school='oldboy'
#
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
#
# def score(self):
# print('%s is scoring'%self.name)
# tea1=OldboyTeacher('egon',18,'male') #会触发OldboyTeacher类(即元类)中的__call__函数
# print(tea1)
# <__main__.OldboyTeacher object at 0x0000000001E51898>
# print(tea1.__dict__)
# {'name': 'egon', 'age': 18, 'sex': 'male'}
# print(object.__new__)
# print(type.__new__)
'''
1 异常处理
错误:
语法上的错误:应该在程序运行前就修改正确
逻辑上的错误:
1 当我们可以预知程序发生错误的添加,应该用if判断去规避错误
AGE=10
age =input('>>: ').strip()
if age.isdigit():
age=int(age)
if age >AGE:
print('too big')
else:
print('必须输入数字')
2 当我们无法预知程序发生错误的条件,也就是说错误一定会发生,那么我们应该
try...except去补救
语法:
try:
被检测的子代码块
except 异常类型1 as e:
匹配成功异常类型1 执行的子代码块
except 异常类型2 as e:
匹配成功异常类型2 执行的子代码块
except 异常类型3 as e:
匹配成功异常类型3 执行的子代码块
except Exception as e:
万能异常
else:
被检测的子代码块没有发生异常时执行的代码块
finnally:
无法被检测的子代码块有无异常发生,都会执行,通常应该在这里进行回收资源的操作
元类:
1 什么是元类:总的来说元类就是类的类
1 一切皆对象: 元类 --(实例化)-->自定义的类--(实例化)-->自定义的对象
1 调用自定义的列得到自定义的对象
2 调用元类得到是自定义的类
2 class关键字的底层原理
1 先拿到类名'Foo'
2 在拿到类的基类们(object,)
3 然后拿到类的名称空间{。。。}
4 调用元类实例化得到自定义的类 Foo=type('Foo',(object,),{...})
2 为什么要用元类
为了控制class关键字的行为
3 如何控制元类
1
class Mymeta(type): #必须是继承type的类才能称之为自定义元类,否则就是一个普通的类
pass
class OldBoyTeacher(metaclass=Mymeta):
pass
2 自定义元类控制类的产生
class Mymetea(type):
def __init__(self,class_name,class_bases,class_dic):
pass
class OldBoyTeacher(metaclass=Mymetea): #OldBoyTeacher=Mymeta('OldBoyTeacher',(object,),{...})
school='OldBoy'
def __init__(self,name):
self.name=name
def score(self):
pass
3 自定义元类控制类的调用(即控制类的实例化得到对象的过程)
class Mymeta(type):
def __init__(self,*args,**kwargs): #self=OldBoyTeacher这个类,arges与kwarges用来接收对象调用时括号内传入的参数
#1 产生一个OldBoyTeacher类空对象
obj=self.__new__(self)
#2 调用OldBoyTeacher下的__init__方法完成对空对象的初始化操作
self.__init__(obj,*args,**kwargs)
#3 返回初始化好的对象
return obj
class OldBoyTeacher(metaclass=Mymeta):
school='OldBoy'
def __init__(self,name):
self.name=name
def score(self):
pass
tea1=OldBoyTeacher('egon')
4 属性查找
'''
"""
# 单列模式实现方式一
import settings #IP='1.1.1.1' PORT=3306
class MySQL:
_instance=None
def __init__(self,ip,port):
self.ip=ip
self.port=port
@classmethod
def form_conf(cls):
if cls._instance is None:
cls._instance=cls(settings.IP,settings.PORT)
return cls._instance
# obj1=MySQL.form_conf()
# obj2=MySQL.form_conf()
# obj3=MySQL.form_conf()
# print(obj1)
# print(obj2)
# print(obj3)
# <__main__.MySQL object at 0x00000000021B17F0>
# <__main__.MySQL object at 0x00000000021B17F0>
# <__main__.MySQL object at 0x00000000021B17F0>
# 传参是相当于实例化走init
# obj4=MySQL('1.2.3',3302)
# print(obj4)
# <__main__.MySQL object at 0x0000000001E818D0>
"""
'''
# 单例模式实现方式二: 装饰器
import settings
#cls是被装饰函数 装饰器可以装饰任意类型,被装饰对象也可以是任意类型
def singleton(cls):
_instance=cls(settings.IP,settings.PORT)
def wrapper(*args,**kwargs):
if len(args) !=0 or len(kwargs) !=0:
#有参数自己实例化
obj=cls(*args,**kwargs)
return obj
return _instance
return wrapper
@singleton #MySQL=singleton(MySQL) #MySQL=wrapper
class MySQL:
def __init__(self,ip,port):
self.ip=ip
self.port=port
# obj=MySQL('1.1.2.1',3306) #obj=wrapper('1.1.2.1',3306)
# print(obj.__dict__)
# {'ip': '1.1.2.1', 'port': 3306}
obj1=MySQL()
obj2=MySQL()
obj3=MySQL()
obj4=MySQL('1.2.3.1',3301)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
# <__main__.MySQL object at 0x00000000027C1668>
# <__main__.MySQL object at 0x00000000027C1668>
# <__main__.MySQL object at 0x00000000027C1668>
# <__main__.MySQL object at 0x0000000001E51860>
'''
"""
# 单例模式实现方式三
import settings
class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic):
#self=MySQL这个类
# MySQL.__instance=MySQL(settings.IP,settings.PORT)
self.__instance=self(settings.IP,settings.PORT)
def __call__(self, *args, **kwargs):
#self=MySQL这个类
if len(args) !=0 or len(kwargs) !=0:
obj=self.__new__(self)
self.__init__(obj,*args, **kwargs)
return obj
return self.__instance
class MySQL(metaclass=Mymeta):
def __init__(self,ip,port):
self.ip=ip
self.port=port
obj1=MySQL()
obj2=MySQL()
obj3=MySQL()
obj4=MySQL('1.2.3.1.1',2231)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
<__main__.MySQL object at 0x00000000027C1828>
<__main__.MySQL object at 0x00000000027C1828>
<__main__.MySQL object at 0x00000000027C1828>
<__main__.MySQL object at 0x00000000027C1898>
"""
'''
# 单列模式实现方式四:
# singleton
# import settings
#
# class MySQL:
# print('run....')
# def __init__(self, ip, port):
# self.ip = ip
# self.port = port
#
# instance=MySQL(settings.IP,settings.PORT)
def f1():
from singleton import instance
print(instance)
def f2():
from singleton import instance,MySQL
print(instance)
obj=MySQL('1,2.1.1',3302)
print(obj)
f1()
f2()
run....
<singleton.MySQL object at 0x00000000021A18D0>
<singleton.MySQL object at 0x00000000021A18D0>
<singleton.MySQL object at 0x0000000002118BA8>
'''