eval、exec及元類、單例實現的5種方法
阿新 • • 發佈:2019-04-27
管理 wrap `` assm 當前 name 出發點 tac 全局
eval內置函數
# 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內置函數
# exec應用場景
# 1.執行字符串沒有執行結果(沒有返回值)
# 2.將執行的字符串中產生的名字形成對應的局部名稱空間
# 3.可以操作全局與局部兩個名稱空間,一般不用關心全局名稱空間
?
source = ‘‘‘
name = ‘Bob‘
age = 20
‘‘‘
class A:
pass
a = A()
?
dic = {}
exec(source, {}, dic)
a.__dict__ = dic # dic = {‘name‘: ‘Bob‘, ‘age‘: 20}
print(a.__dict__)
print(a.name)
print(a.age)
元類
# 元類:類的類
# 通過class產生的類,也是對象,而元類就是用來產生該對象的類
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‘, (), l_d)
print(Student)
?
?
type產生類
# 類是type的對象,可以通過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)
?
?
單例
# 單例:一個類只能產生一個實例
# 為什麽要有單例:
# 1.該類需要對象的產生
# 2.對象一旦產生,在任何位置再實例化對象,只能得到第一次實例化出來的對象
# 3.在對象唯一創建後,可以通過屬性修改或方法間接修改屬性,來完成數據的更新,不能通過實例化方式更新數據
?
## 單例
?
```python
#實現單例方法1--類方法及類封裝屬性
class Song:
__instance = None
def __init__(self):
pass