面向對象之元類

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.在對象惟一建立後,能夠經過屬性修改或方法間接修改屬性,來完成數據的更新,不能經過實例化方式更新數據
相關文章
相關標籤/搜索