eval 内置函数
# 将字符串作为执行目标,得到相应结果
eval 内置函数的使用场景:
1、执行字符串会得到相应的执行结果
2、一般用于类型转换,得到dict、list,tuple等
# 将这串字符串写到文件 1.txt 中, 文件中是不带引号的,只是读成字符串到python中
dir_str = "{'a': 1, 'b': 2, 'c': 3}"
with open(1.txt, 'r', encoding='utf-8') as f:
data_str = f.read()
"{'a': 1, 'b': 2, 'c': 3}" => {'a': 1, 'b': 2, 'c': 3}
res = eval(data_str)
print(res, type(res))
run==>
{'a': 1, 'b': 2, 'c': 3} <class 'str'>
exec 内置函数
exec 内置函数的使用场景:
1、执行字符串没有执行结果(没有返回值)
2、将执行的字符串中产生的名字形成对应的局部名称空间
source = '''
name = 'Bob'
age = 20
'''
class A:
pass
a = A()
dic = {}
# 将source中的数据放入到dic的名称空间字典中
exec(source, {}, dic)
# 将存有数据的dic 赋值给 对象 a 的名称空间
a.__dict__ = dic
print(a.__dict__) # {'name': 'Bob', 'age': 20}
print(a.name) # Bob
print(a.age) # 20
type产生类
# 类是type的对象,可以通过type(参数)来创建类
type(name, bases, namespace)
Python中万物皆对象,所有用来创建对象的类,本身也是对象,类是type类的对象
type类叫做元类,是所有元类的基类
元类:造类的类 - 类的类
-- 控制类的产生
-- 控制类的对象的产生
s = '''
my_a = 10
my_b = 20
def __init__(self):
pass
@classmethod
def print_msg(cls, msg):
print(msg)
'''
dic = {}
exec(s, {}, dic)
# 把s中产生的数据放到dic名称空间中,再把这个名称空间给 类C
C = type('C', (object, ), dic)
print(C, type(C), C.__bases__)
# <class '__main__.C'> | <class 'type'> | (<class 'object'>,)
c1 = C()
print(c1.my_a) # 10
c1.print_msg('wjw') # wjw
自定义元类
# 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类实质上是由元类实例化出来的
Student = type('student', (object, ), namespace)
class MyMeta(type): # 继承元类,那么MyMeta也变成了元类
自定义一个元类,然后重写__init__方法的目的:
1、最终的工作(如何开辟空间,如何操作内存)还是要借助type中的功能
2、该__init__方法是从type中继承来的,所以type的__init__接收到的参数是相同的
3、在交给type最终完成工作之前,可以对类的创建加以限制 *****
def __init__(self, className, bases, namespace):
# 需求:由元类控制的类的类型必须首字母大写
if not className.istitle(): # 目的 3
# 自定义异常处理,如果不是大写就报错
raise NameError('名字首字母必须大写')
# super(MyMeta, cls).__init__(class_name, bases, namespace)
super().__init__(className, bases, namespace) # 目的 1 和 2
自定义元类,重写__call__方法的目的:
1、被该元类控制的类 生成对象 时,会调用元类的__call__方法
2、在call中的返回值就是创建的对象
3、在call中
3.1 -- 通过object开辟空间产生对象
3.2 -- 用被控制的类回调到自己的init方法完成名称空间的赋值
3.3 -- 将修饰好的对象反馈给外界
def __call__(cls, *args, **kwargs): # 目的 1
obj = object.__new__(cls) # 目的 3.1
# 用object中的__new__方法新建一个名称空间给元类所控制的类的对象
# 需求:所有通过该元类控制的类产生的对象都有mata_name属性
obj.meta_name = cls.__name__
# 在obj名称空间中新建一个 meta_name = cls.__name
# 调回当前被控制的类自身的init方法,完成名称空间的赋值
cls.__init__(obj, *args, **kwargs) # 目的 3.2
return obj # 目的 2 和 3.3
class Student(object, metaclass=MyMeta): # 继承元类MyMeta
def __init__(self, name, age):
self.name = name
self.age = age
# class Student: <==> MyMeta/type(className, bases, namespace)
# 测试
stu = Student('Bob', 18)
print(stu, stu.name, stu.age)
# <__main__.Student object at 0x000000000254A7F0> | Bob | 18
stu = Student('Tom', 20)
print(stu.meta_name) # Student # call中强制定义的属性也生效了
单例
单例:一个类只能产生一个单例
为什么要有单例:
1、该类需要对象的产生
2、对象一旦产生,在任何位置再实例化对象, 只能得到第一次实例化出来的对象
3、在对象唯一创建后,可以通过属性修改或方法间接修改属性,来完成数据的更新,不能通过实例化方式更新数据
单例化类的方法:
方法一:
约定用 类名() 的方式来实例化对象, 用类方法来获取唯一对象
class clsName():
__instance = None
@classmethod # 用类直接调用
def getInstance(cls):
if get.__instance == None:
cls.instance = cls() # 示例化出对象
return cls.instance # 返回实例化出来的对象
s1 = Songs.getInstance()
s2 = songs.getInstance()
print(s1, s2)
<__main__.Songs object at 0x00000000023835F8>
<__main__.Songs object at 0x00000000023835F8>
方法二:
在类中 重写__new__方法来控制类的实例化
class Songs:
__instance = None
def __new__(cls, songName, *args, **kwargs):
if cls.__instance == None:
# 调用object的__new__为类的对象创建名称空间
cls.__instance = object.__new__(cls)
# 往名称空间中创建一个songName属性
cls.__instance.songName = songName
return cls.__instance #
# 用来修改对象属性的方法
def change_song(self, songName):
self.songName = songName
s1 = Songs('不谓侠')
s2 = Songs('如寄')
print(s1.songName, s2.songName) # 不谓侠 不谓侠
s2.change_song('如寄')
print(s1.songName, s2.songName) # 如寄 如寄
方法三:
装饰器认证是否实例化过,不是则实例化,是则不重新实例化
def outter(cls):
_instance = None
def inner(*args, **kwargs):
nonlocal _instance
if _instance == None:
instance = cls(*args, **kwargs)
return instance
return inner
@outter
class Songs:
pass
s1 = Songs()
s1 = Songs()
print(s1, s2)
方法四:
元类
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)