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.將執行的字符串中產生的名字造成對應的局部名稱空間 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(參數)來建立類 # 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.在對象惟一建立後,能夠經過屬性修改或方法間接修改屬性,來完成數據的更新,不能經過實例化方式更新數據