exec , 元类,__new__, __call__ , 单例模式 , 异常
1,类也是对象
'''
动态语言
可以在运行期间 动态生成类 修改对象属性
静态语言
''''' '''
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
'''
obj = type("TestClass",(object,),{})
print(obj) #<class '__main__.TestClass'> class B(object): #type("B",(object,),{"name":"rose"})
name = "rose" #模拟解释器创建类的过程
def test1(a):
print(a) def test2(self,b):
print(self,b) class_name = "C"
bases = (object,)
name_dic = {"name":"jack","test1":test1,"test2":test2} C = type(class_name,bases,name_dic)
# print(C) #<class '__main__.C'>
c1 = C()
print(c1) #<__main__.C object at 0x000001EFEC877550>
c1.test2(100) #<__main__.C object at 0x0000021F31807550> 100
2 , exec
glob = {}
locl = {} code = """
def test(a):
print(a)
""" exec(code,glob,locl) # print(glob) #打印系统内置函数
print(locl) #{'test': <function test at 0x000001376F36C2F0>}
locl["test"](100) #exec 可以执行字符串形式的python代码,并且会把执行过程中产生的名字,放到局部名称空间中
class_test = """
class A:
def test(self):
print(self)
"""
loca2 = {}
exec(class_test,None,loca2)
print(loca2) #{'A': <class '__main__.A'>} # eval(class_test) #报错,eval用于处理单行字符串的表达式
3,元类
class person(): def __init__(self,name):
self.name = name def SAYHI(self):
print(self.name) '''
类名必须大写开头,方法名必须全部小写
应用场景:用于限制类,满足某些条件,例如上述要求
type类已经具备了创建类的能力,但是现在不能满足我们的要求
需要对已有的功能进行扩展或修改
方式:
1,直接修改源代码 ,行不通
2,自定义新的元类
'''
class MyMetaClass(type):
pass #默认创建类时,是找的type来实例化的
class Person(metaclass=MyMetaClass):
pass class Student:
def __init__(self):
pass print(type(Person)) #<class '__main__.MyMetaClass'>
print(type(Student)) #<class 'type'> s = Student() #实例化对象时, 1,产生空对象,2,自动执行__init__ #创建类对象时也是一样的,会先创建空的类对象,在调用__init__()方法
# Person = MyMetaClass()
class MyMetaClass(type):
def __init__(self,class_name,bases,name_dic):
#元类中的self表示的都是类对象
print(self) #<class '__main__.Student'> #不要忘记调用父类的初始化
super().__init__(class_name,bases,name_dic)
print(name_dic) #类名必须首字母大写,否则直接抛出异常
if not class_name.istitle():
print('类名必须大写!')
raise Exception #控制类中方法名必须全部小写
for k in name_dic:
if str(type(name_dic[k])) == "<class 'function'>":
if not k.islower():
raise Exception('方法名必须全小写!') #会自动调用其元类中的__init__方法传入,类对象本身,类名称,父类们,名称空间
class Student(object,metaclass=MyMetaClass): #MyMetaClass("Student",(object,),{})
NAME = 10
def asdfA(self):
print('SNY')
3 , 元类中 __new__
class MeMetaClass(type): def __init__(self,class_name,bases,name_dic):
# super().__init__(class_name,bases,name_dic)
print("init") #该方法会在实例化类对象时自动调用并且在__init__之前调用
#其作用是用于创建新的类对象的
#注意这里必须调用type类中的__new__否则将无法产生类对象,并且返回其结果
def __new__(cls, *args, **kwargs):
#cls 表示元类自己即MyMetaClass
print("new")
print(args,kwargs) #('Person', (), {'__module__': '__main__', '__qualname__': 'Person'}) {}
return type.__new__(cls,*args,**kwargs) #如果覆盖__new__一定要写上这行代码 class Person(metaclass=MeMetaClass):
pass print(Person) #<class '__main__.Person'> #就算__init__中什么都不写,这个类对象其实已经创建完成了,该有的属性都有了
#这是与普通类不同之处 print(Person.__name__) #不会报错 class Student:
def __init__(self,name):
pass s = Student('张三')
# s.name #报错
#练习1: #需求:要求每个类必须包含__doc__属性,__doc__用于访问一个对象的注释信息
class A:
'''
this is A
'''
pass print(A.__doc__) #如果你要控制类的创建,那就自定义元类 覆盖__init__
class DocMetaClass(type):
def __init__(self,class_name,bases,name_dic):
super().__init__(class_name,bases,name_dic) # if not("__doc__" in name_dic and name_dic["__doc__"]):
# raise Exception #如果doc为空,则抛异常
if not self.__doc__:
raise Exception class Person(metaclass=DocMetaClass):
pass print(type(object))
4 , 元类中 __call__
class Person:
#调用对象时,会执行对象所在类中的__call__方法
def __call__(self, *args, **kwargs):
print("call")
print(args)
print(kwargs) p = Person()
p() '''
练习:将类中的为字符串的属性名转为大写
'''
class MyMeta(type):
#获得某个类的实例
def __call__(self, *args, **kwargs):
print("call")
# return super().__call__(*args,**kwargs)
print(args) #('jack', 'women', 18)
print(kwargs) #{} new_args = []
for i in args:
if isinstance(i,str):
new_args.append(i.upper())
else:
new_args.append(i)
print(new_args) #['JACK', 'WOMEN', 18]
return super().__call__(*new_args,**kwargs) #注意:__new__ __init__是创建类对象时还会执行
#__call__ 类对象要产生实例时执行 class Student(metaclass=MyMeta):
def __init__(self,name,gender,age):
self.name = name
self.gender = gender
self.age = age s = Student('jack','women',18)
print(s.age) #
print(s.gender) #WOMEN class Person(metaclass=MyMeta):
def __init__(self,name,gender):
self.name = name
self.gender = gender p = Person('rose','name')
print(p.name) #ROSE
5, 单例模式
'''
单例模式
是一种设计模式,是单个实例的意思
当你需要 让你的类仅有一个实例时,那就可以使用单例模式
'''''
class Person:
obj = None
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender def say(self):
print('my name is %s my 姑姑 is 龙妈'%self.name) @classmethod
def get_instance(cls):
if not cls.obj:
obj = cls('小龙女',19,'women')
cls.obj = obj
print('创建新的了')
return cls.obj # 调用了多次,产生了多个实例 (地址不一样)
p1 = Person('姬如雪','','women')
p1.say()
p2 = Person('姬如雪','','women')
p2.say()
print(p1,p2) #<__main__.Person object at 0x000001A5A87076A0> <__main__.Person object at 0x000001A5A8707710> #限制了类的实例化,如果为同一个类则只实例化一次 (地址一样)
p1 = Person.get_instance()
p1.say()
p2 = Person.get_instance()
p2.say() print(p1) #<__main__.Person object at 0x000002396C2F75C0>
print(p2) #<__main__.Person object at 0x000002396C2F75C0>
6 , 元类实现单例
class SingMeta(type):
# 创建类时会执行__init__,在这为每一类设置一个obj属性 默认为None
def __init__(self, a, b, c):
super().__init__(a, b, c)
self.obj = None
print(self.obj) # 当类要创建对象时会执行该方法
def __call__(self, *args, **kwargs):
# 判断这个类如果已经有了实例了就直接返回,从而实现单例
if self.obj:
return self.obj # 如果没有,则创建新的实例保存到类中
obj = type.__call__(self, *args, **kwargs)
self.obj = obj
return obj class Person(metaclass=SingMeta):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender def say(self):
print("my name is %s my 姑姑 is 龙妈" % self.name) class Student(metaclass=SingMeta):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender=gender def say(self):
print("my name is %s my 姑姑 is 龙妈" % self.name) p1 = Person('姬如雪',20,'women')
p2 = Person('姬如雪',20,'women')
print(p1) #<__main__.Person object at 0x000001F512867668>
print(p2) #<__main__.Person object at 0x000001F512867668> stu1 = Student('史蒂夫',18,'man')
stu2 = Student('史蒂夫',18,'man')
print(stu1) #<__main__.Student object at 0x0000013B18EB7780>
print(stu2) #<__main__.Student object at 0x0000013B18EB7780>
7, 单例案例:
class Single(type):
def __init__(self,a,b,c):
super().__init__(a,b,c)
self.obj = None def __call__(self, *args, **kwargs):
if self.obj:
return self.obj obj = type.__call__(self,*args,**kwargs)
self.obj = obj
return obj class QQPlayer(metaclass=Single):
def __init__(self,voice_value,repeat=False):
self.voice_value =voice_value
self.repeat = repeat def play(self,file_path):
if hasattr(self,'file_path'):
self.stop() print('正在播放%s'%file_path)
self.file_path = file_path def stop(self):
print('%s--停止播放'%self.file_path) #问题:每次播放一次,都是实例化一次
ply = QQPlayer(100,True)
ply.play('如果.mp3') ply1 = QQPlayer(100,True)
ply1.play('后来.mp3') ply2 = QQPlayer(100,True)
ply2.play('田鸥.mp3') print(ply) #<__main__.QQPlayer object at 0x000002B349C87550>
print(ply1) #<__main__.QQPlayer object at 0x000002B349C87550>
print(ply2) #<__main__.QQPlayer object at 0x000002B349C87550>
8, 常见异常
'''
语法错误: SyntaxError: invalid syntax
'''''
# if num > 1 # print('hello')
# a =
# b = 10 '''
类型错误: TypeError: 'int' object is not subscriptable
'''
# 1[:] '''
下标错误: IndexError: list index out of range
'''
# li = [1,2,3,4]
# print(li[10]) '''
KeyError: 'xxx'
'''
# {'name':1}['xxx'] '''
FileNotFoundError: [Errno 2] No such file or directory: 'xxx'
'''
# with open('xxx')as f:
# pass '''
NameError: name 'name' is not defined
'''
# def func():
# name
# pass
# func() '''
1,捕捉异常
'''
#语法一:
try:
print('start')
{'name':1}['xxx']
print('over')
except:
print(' key 不存在') #语法二: 在except 中指定要处理的异常类型
try:
print('start')
{'name':1}['xxx']
1[:]
print('over')
except KeyError:
print('出问题了') #语法三 : 在except中可以指定多种异常类型,使用统一的处理方案,没啥用
try:
print('start')
{'name':1}['xxx']
1[:]
print('over')
except(KeyError,TypeError):
print('出问题了') #语法四 : 一个try可以跟多个except语句 每个处理不同的异常
try:
print('start')
{'name': 1}['xxx']
1[:]
print('over')
except KeyError:
print('Key 不存在!')
except TypeError:
print('要操作的类型不对啊!') # 语法5 万能异常 尽量少用 因为 无法知道具体原因
try:
print("start")
# {"name":1}["xxx"]
# 1[:]
# name
print("over")
except Exception:
print("不知道啥原因 反正有问题!") # 语法6 给异常对象取别名 从而访问一异常对象
# 之所以 能处理任何类型 是因为 Exception 是所有异常类的父类
try:
print("start")
# {"name":1}["xxx"]
1[:]
# name
print("over")
except Exception as e:
print("有问题! 原因为%s" % e)
print(type(e)) # 最常用的方式 在处理异常时 一定要记得打印一下异常信息 否则 你的程序不会出问题 但是也不会正常运行
try:
name
except NameError as e:
print(e) # 观光语法 else 将在代码没有异常时执行
try:
a = 10
except Exception as e:
print(e)
else:
print("else???????? ") class FileTypeException(Exception):
pass class Player:
def play(self,path):
if not path.endswith("mp3"):
# print("文件类错误!")
# z主动抛出异常
raise FileTypeException("仅能播放mp3格式.....")
print("播放%s" % path) assert path.endswith("mp3")
print("播放%s" % path) p = Player()
p.play("xxx.mp4")
exec , 元类,__new__, __call__ , 单例模式 , 异常的更多相关文章
- 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理
原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...
- 29 内置方法 eval | exec 元类 单例
eval与exec内置方法 将字符串作为执行目标,得到响应结果 eval常用作类型转换:该函数执行完有返回值 exec拥有执行更复杂的字符串:可以形成名称空间 eval内置函数的使用场景: 1.执 ...
- python 之 面向对象(元类、__call__、单例模式)
7.13 元类 元类:类的类就是元类,我们用class定义的类来产生我们自己的对象的,内置元类type是用来专门产生class定义的类 code=""" global x ...
- 面向对象高级C(元类补充及单例模式)
元类有关知识点补充 #类的名称空间 类的名称空间不能用类似字典的方法修改,例如School类里面有name属性xxx,那么我用School.__dict__['name'] = 'yyy'就会报错&q ...
- [Python之路] 元类(引申 单例模式)
一.类也是对象 当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射: def A(): print("This is function A" ...
- 通过 python的 __call__ 函数与元类 实现单例模式
简单一句话,当一个类实现__call__方法时,这个类的实例就会变成可调用对象. 直接上测试代码 class ClassA: def __call__(self, *args, **kwargs): ...
- 类和对象的创建过程(元类,__new__,__init__,__call__)
一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...
- python 入门基础24 元类、单例模式
内容目录: 一.元类 二.单例模式 一.元类 1 什么是元类: 源自一句话:在python中,一切皆对象,而对象都是由类实例化得到的 class OldboyTeacher: def __init__ ...
- day37-2元类,单例模式
目录 元类 造类的第一种形式 class做了什么事 控制元类产生的类 控制元类产生的对象 实例化类 加上元类后类的属性查找顺序 元类控制模版 单例模式 1. 使用类方法的特性 2. 使用装饰器 3. ...
随机推荐
- 使用Fsharp 探索 Dotnet 平台
Fsharp的交互开发环境使得我们在了解DotNet平台时能够快速的获得需要的反馈. 反馈在任何技艺的磨练过程中必不可少,我认为也是最重要的环节之一.在“一万小时天才理论”中,著名的髓鞘质就是在快速有 ...
- hibernate课程 初探单表映射3-1 hibernate单表操作简介
本章简介: 1 单一主键 2 基本类型 3 对象类型 4 组件属性 5 单表操作CRUD实例
- new Date(str)返回的时间结果在移动端比PC端快了8小时
最近开发过程中,后端传过来一个“2018-03-15T17:53:19.6307928”字符串,需要将字符串转换成“2018-03-15 17:53”的格式展示出来.首先我使用了var time=n ...
- Java正则表达式—小应用—简易爬虫
在上一篇中,学习了正则表达式的四个功能.即匹配.分割.替换.获取. 利用获取功能,可以实现简单的网页爬虫. 4,获取:将字符串中的符合规则的子串取出. 获取功能的操作步骤: 1,将正则表达式 ...
- Git命令--保存用户名和密码
使用git各项操作时,总是会出现输入密码的弹窗,且需要多次输入,很是繁琐,通过git命令可以记住密码,避免多次操作. 一.创建保存密码的文件 1.在home文件夹,一般是 C:\Documents a ...
- Myeclipse 突然打不开的问题
用的好好的Myeclipse今天突然打不开了,打开myeclipse提示 :an error has occurred see the log file 然后我打开日志文件,看到如下的报错信息: ! ...
- 【MATLAB】设定坐标的轴的范围
set(gca,'XLim',[0 1.5]);%X轴的数据显示范围set(gca,'XTick',[0:0.1:1.5]);%设置要显示坐标刻度set(gca,'XTickLabel',[0:0.1 ...
- IDA逆向:结构体的逆向
源代码: int _tmain(int argc, _TCHAR* argv[]) { struct v1 { int a; short b; char c; int d; double e; }; ...
- POJ 3233 Matrix Power Series (矩阵分块,递推)
矩阵乘法是可以分块的,而且幂的和也是具有线性的. 不难得到 Si = Si-1+A*Ai-1,Ai = A*Ai-1.然后矩阵快速幂就可以了. /*************************** ...
- python_39_变量补充
#使用eval()函数计算字符串中的有效表达式,并返回结果 a='1+3' print(eval(a)) b='''{ '闵行': { '人民广场': { '炸鸡店': {}, }, } ''' pr ...