29 内置方法 eval | exec 元类 单例
阅读原文时间:2024年06月24日阅读:1

  将字符串作为执行目标,得到响应结果

  eval常用作类型转换:该函数执行完有返回值

  exec拥有执行更复杂的字符串:可以形成名称空间

eval内置函数的使用场景:
   1.执行字符串会得到相应的执行结果
   2.一般用于类型转化,得到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应用场景
 1.执行字符串没有执行结果(没有返回值)
 2.将执行的字符串中产生的名字形成对应的局部名称空间

source = '''
name = 'Bob'
age = 20
'''
class A:
pass
a = A()

dic = {}

可以操作全局与局部两个名称空间,一般不用关心全局名称空间

exec(source, {}, dic)
a.__dict__ = dic
print(a.__dict__) # {'name': 'bob', 'age': 20}
print(a.name)
print(a.age)

元类:类的类
  通过class产生的类,也是对象,而元类就是用来产生该对象的类

  类是type的对象,可以通过type(参数)来创建类

local_str = """
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print(self.name + '在学习')
"""
local_dic = {}
exec(local_str, {}, local_dic)
Student = type('Student', (), local_dic) # 产生一个Student类
print(Student)

type创建类

# type(name, bases, namespace)

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 MyMeta(type):
# 控制类的创建过程
def __init__(cls, class_name, bases, namespace):
print(cls, class_name, bases, namespace)
super().__init__(class_name, bases, namespace)

def \_\_call\_\_(cls, \*args, \*\*kwargs):  
    obj = object.\_\_new\_\_(cls)  
    cls.\_\_init\_\_(obj, \*args, \*\*kwargs)  
    return obj

Student类与Student类的对象产生都可以备元类MyMeta控制

class Student(metaclass=MyMeta):
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('owen', 18)
print(stu.name)

# 单例1
class MyMeta(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = cls.__new__(cls)
cls.instance.__init__(*args, **kwargs)
return cls.instance

class A(metaclass=MyMeta):
def __init__(self):
self.ip = '1.1.1.0'

  一个类只能产生一个实例
  为什么要有单例:
    1.该类需要对象的产生
    2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
    3.在对象唯一创建后,可以通过属性修改或方法间接修改属性,来完成数据的更新,不能通过实例化方式更新数据

# 单例2
class Song:
__instance = None
def __init__(self):
pass
@classmethod
def getInstance(cls):
if cls.__instance == None:
cls.__instance = cls()
return cls.__instance
s1 = Song.getInstance()
s2 = Song.getInstance()
print(s1, s2)

# 单例3

def singleton(cls):
_instance = None
def getInstance(*args, **kwargs):
nonlocal _instance
if _instance == None:
_instance = cls(*args, **kwargs)
return _instance
return getInstance

@singleton
class A:
def __init__(self, num):
self.num = num

print(A(1), A(2), A(3))

print(A(1).num, A(2).num, A(3).num) # 1 1 1

# 单例4

class A:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance == None:
cls.__instance = super().__new__(cls)
return cls.__instance
print(A(), A())

# 单例5

# single_module.py
class Single:
pass
singleton = Single()

测试文件

from single_module import singleton
print(singleton)
print(singleton)