1. 程式人生 > 其它 >演算法---之插入排序

演算法---之插入排序

目錄

  • 反射實際案例

  • 面向物件的雙下方法

  • 元類

內容

1.反射實際案例

利用面向物件編寫系統終端功能

class WinCmd(object):
    def ls(self):
        print('')
    def dir(self):
        print('windows系統正在執行dir命令')
    def cd(self):
        print('windows系統正在執行cd命令')

class LinuxCmd(object):
    def ls(self):
        print('Linux系統正在執行ls命令
') def dir(self): print('Linux系統正在執行dir命令') def cd(self): print('Linux系統正在執行cd命令') obj = WinCmd() obj1 = LinuxCmd()

反射提供了一種不需要考慮程式碼的前提下 操作資料和功能

def run(obj):
    while True:
        cmd = input('請輸入您的指令>>>:')
        if hasattr(obj, cmd):
            func_name = getattr(obj, cmd)
            func_name()
        
else: print('cmd command not found') run(obj1) run(obj)

面向物件的雙下方法

1.__str__

物件被執行列印(print,前端展示)操作的時候會自動觸發

該方法必須返回字串型別的資料

很多時候用來更加精準的描述物件

2.__del__

物件被執行(被動,主動)刪除操作之後自動執行

3.__getattr__

物件查詢不存在名字的時候自動觸發

4.__setattr__

物件在執行新增屬性操作的時候自動觸發

5.__call__

物件被加括號呼叫的時候自動觸發

6.__enter__ , __exit__

被執行with語法自動觸發 繫結在一起

7.__getattribute__

只要物件查詢名字無論名字是否存在都會執行該方法

如果類中有__getattribute__方法,那麼就不會執行__getattr__方法

8.__new__

下面將元類會提及

面試題實戰

1.讓字典具備句點符查詢值的功能

class MyDict(dict):
      def __getattr__(self, item):
          return self.get(item)

      def __setattr__(self, key, value):
          self[key] = value

obj = MyDict({'name':'zhou','age':18})

具備句點符取v

print(obj.name) # zhou
print(obj.age) # 18

句點符設k:v

obj['gender'] = 'male'
obj.pwd = 123
print(obj) # {'name': 'jason', 'age': 18, 'gender': 'male', 'pwd': 123}

2.補全下列程式碼 使其執行不報錯

題目:

class Context:
        pass
with Context() as ctx:
    ctx.do_something()

解:

 class Context:
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass
    def do_something(self):
        pass
    with Context() as ctx:
    ctx.do_something()

元類

元類:產生類的類

根據前面學過的 type 知識點:

print(type(123)) # <class 'int'>
print(type([12, 33, 44])) # <class 'list'>
print(type({'name':'zhou','pwd':123})) # <class 'dict'>

這是我們注意到:class

type檢視的其實是當前物件所屬的類名稱

class MyClass(object):
    pass
obj = MyClass()
print(type(obj))  # <class '__main__.MyClass'>
print(type(MyClass))  # <class 'type'>

class Student:
    pass
print(type(Student))  # <class 'type'>

class Teacher(MyClass):
    pass
print(type(Teacher))  # <class 'type'>

再結合元類的概念可得知:

type 就是所有類預設的元類!!!

產生類的兩種表現形式(本質是一種)

1.class關鍵字

class C1(object):
    pass
    print(C1)  # <class '__main__.C1'>

2.type元類

type(類名,父類,類的名稱空間)
res = type('C1', (), {})
    print(res)  # <class '__main__.C1'>

學習元類的目的:元類能夠控制類的建立 也就意味著我們可以高度定製類的行為

eg:掌握了物品的生產過程 就可以在過程中做任何的額外操作

元類的基本使用

元類是不能通過繼承的方式直接指定的 需要通過關鍵字引數的形式修改

class MyTypeClass(type):
    pass
class C1(MyTypeClass):
    pass
print(C1) # <class '__main__.C1'>
print(type(C1)) # <class 'type'>

直接繼承列印結果是沒有反應

而這裡需要的關鍵字引數就是:metaclass

class MyTypeClass(type):
    pass
class C1(metaclass=MyTypeClass):
    pass
print(type(C1)) # <class '__main__.MyTypeClass'>
class MyTypeClass(type):
    def __init__(cls, cls_name, cls_bases, cls_dict):
        # print(cls, cls_name, cls_bases, cls_dict)
        if not cls_name.istitle():
            raise Exception("類名的首字母必須大寫 你個SD")
        super().__init__(cls_name, cls_bases, cls_dict)

class C1(metaclass=MyTypeClass):
    school = '清華大學'

class a(metaclass=MyTypeClass):
    school = '清華大學'

元類進階操作

回想__call__方法

物件加括號會自動執行產生該物件的類裡面的__call__,並且該方法返回什麼物件加括號就會得到什麼

推導:類加括號會執行元類的裡面的__call__該方法返回什麼其實類加括號就會得到什麼

類裡面的__init__方法和元類裡面的__call__方法執行的先後順序!!!

class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        print('__call__ run')
        super().__call__(*args, **kwargs)
class MyClass(metaclass=MyTypeClass):
      def __init__(self, name):
          print('__init__ run')
          self.name = name
obj = MyClass('jason')

定製物件的產生過程

class MyTypeClass(type):
    def __call__(self, *args, **kwargs):
        # print('__call__ run')
        # print(args,kwargs)
        if args:
            raise Exception('必須全部採用關鍵字引數')
        super().__call__(*args, **kwargs)

class MyClass(metaclass=MyTypeClass):
    def __init__(self, name):
        # print('__init__ run')
        self.name = name

強制規定:類在例項化產生物件的時候 物件的獨有資料必須採用關鍵字引數

obj1 = MyClass('jason')
obj2 = MyClass(name='jason')

如果你想高度定製類的產生過程:編寫元類裡面的__init__方法

如果你想高度定製物件的產生過程:編寫元類裡面的__call__方法

雙下new方法

__new__用於產生空物件(類)     骨架  

__init__用於例項化物件(類)       血肉

注意:並不是所有的地方都可以直接呼叫__new__ 該方法過於底層

如果是在元類的__new__裡面 可以直接呼叫

class Meta(type):
      def __new__(cls, *args, **kwargs):
          obj = type.__new__(cls,*args,**kwargs)
          return obj
    如果是在元類的__call__裡面 需要間接呼叫
        class Mate(type):
      def __call__(self, *args, **kwargs):
          obj = object.__new__(self) # 建立一個空物件
          self.__init__(obj,*args,**kwargs) # 讓物件去初始化
          return obj