eval内置函数
eval内置函数的使用场景:
- 执行字符串会得到相应的执行结果
- 一般用于类型转化,得到dict、list、tuple等
dic_str = "{'a': 1, 'b': 2, 'c': 3}"
print(eval(dic_str))
list_str = "[1, 2, 3, 4, 5]"
print(eval(list_str))
tuple_str = "(1, 2, 3, 4, 5)"
print(eval(tuple_str))
exec内置函数
exec应用场景
- 执行字符串没有执行结果(没有返回值)
- 将执行的字符串中产生的名字形成对应的局部名称空间
source = '''
name = 'Bob'
age = 20
'''
class A:
pass
a = A()
dic = {}
exec(source, {}, dic)
a.__dict__ = dic
print(a.__dict__)
print(a.name)
print(a.age)
type产生类
- 类是type的对象,可以通过type(参数)来创建类
s = '''
my_a = 10
my_b = 20
def __init__(self):
pass
@classmethod
def print_msg(cls, msg):
print(msg)
'''
namespace = {}
exec(s, {}, namespace)
Student = type('Student', (object, ), namespace)
stu = Student()
自定义元类
- 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了
Student = type('Student', (object, ), namespace)
class MyMeta(type):
# 在class Student时调用:Student类的创建 => 来控制类的创建
# 自定义元类,重写init方法的目的:
# 1.该方法是从type中继承来的,所以参数同type的init
# 2.最终的工作(如果开辟空间,如果操作内存)还是要借助type
# 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
def __init__(cls, class_name, bases, namespace):
# 目的:对class_name | bases | namespace加以限制 **********************
super().__init__(class_name, bases, namespace)
# 在Student()时调用:Student类的对象的创建 => 来控制对象的创建
# 自定义元类,重写call方法的目的:
# 1.被该元类控制的类生成对象,会调用元类的call方法
# 2.在call中的返回值就是创建的对象
# 3.在call中
# -- 通过object开辟空间产生对象
# -- 用被控制的类回调到自己的init方法完成名称空间的赋值
# -- 将修饰好的对象反馈给外界
def __call__(cls, *args, **kwargs):
# 目的:创建对象,就可以对对象加以限制 **********************
obj = object.__new__(cls) # 通过object为哪个类开辟空间
cls.__init__(obj, *args, **kwargs) # 调回当前被控制的类自身的init方法,完成名称空间的赋值
return obj
# 问题:
# 1.继承是想获得父级的属性和方法,元类是要将类的创建于对象的创建加以控制
# 2.类的创建由元类的__init__方法控制
# -- 元类(class_name, bases, namespase) => 元类.__init__来完成实例化
# 3.类的对象的创建由元类的__call__方法控制
# -- 对象产生是需要开辟空间,在__call__中用object.__new__()来完成的
class Student(object, metaclass=MyMeta):
pass
# class Student: <=> type(class_name, bases, namespace)
单例
为什么要有单例:
- 该类需要对象的产生
- 对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
单例的实现:
class Songs():
__instance = None
@classmethod
def getInstance(cls):
# 对象没有创建返回,有直接返回
if cls.__instance == None:
cls.__instance = cls()
return cls.__instance
s1 = Songs.getInstance()
s2 = Songs.getInstance()
print(s1, s2)
1
class Songs:
__instance = None
def __new__(cls, song_name, *args, **kwargs):
if cls.__instance == None:
cls.__instance = object.__new__(cls)
cls.__instance.song_name = song_name
return cls.__instance
def change_song(self, song_name):
self.song_name = song_name
s1 = Songs('菊花爆满山')
s2 = Songs('感觉身体被掏空')
print(s1.song_name, s2.song_name) # 菊花爆满山 菊花爆满山
s2.change_song('感觉身体被掏空')
print(s1.song_name, s2.song_name) # 感觉身体被掏空 感觉身体被掏空
2
def outer(cls):
_instance = None
def inner(*args, **kwargs):
nonlocal _instance
if _instance == None:
_instance = cls(*args, **kwargs)
return _instance
return inner
@outer # Songs = outer(Songs)
class Songs:
pass
s1 = Songs()
s2 = Songs()
print(s1, s2)
3
class SingleMeta(type):
__instance = None
def __call__(cls, *args, **kwargs):
if SingleMeta.__instance == None:
SingleMeta.__instance = object.__new__(cls)
cls.__init__(SingleMeta.__instance, *args, **kwargs)
return SingleMeta.__instance
class Songs(metaclass=SingleMeta):
def __init__(self):
pass
pass
s1 = Songs()
s2 = Songs()
print(s1, s2)
4