日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

反射機制是面向對象編程語言中比較重要的功能,可以動態獲取對象信息以及動態調用對象,Python/ target=_blank class=infotextkey>Python作為一門動態編程語言,當然也有反射機制,本文介紹Python反射函數使用方法。

反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力。

在程序運行時可以獲取對象類型定義信息,例如,Python中的type(obj)將返回obj對象的類型,這種獲取對象的type、attribute或者method的能力稱為反射。通過反射機制,可以用來檢查對象里的某個方法,或某個變量是否存在。也就是可以通過字符串映射對象的方法或者屬性。

Python反射函數

Python反射常用的內置函數

  • type(obj):返回對象類型
  • isinstance(object, classinfo):判斷一個對象是否是一個已知的類型,類似 type()
  • callable(obj):對象是否可以被調用
  • dir([obj]):返回obj屬性列表
  • getattr(obj, attr):返回對象屬性值
  • hasattr(obj, attr):判斷某個函數或者變量是否存在
  • setattr(obj, attr, val):給模塊添加屬性(函數或者變量)
  • delattr(obj, attr):刪除模塊中某個變量或者函數

反射函數使用方法

先創建一個類:

class Person():
    def __init__(self, x, y):
        self.age = x
        self.height = y
        
    def __new__(cls, *args, **kwargs):
        print("begin!!!")
        return object.__new__(cls)
        
    def __call__(self, *args, **kwargs):
        print("hello!!!")

    def talk(self):
        print(f"My age is {self.age} and height is {self.height}")

dir()

利用反射的能力,我們可以通過屬性字典__dict__來訪問對象的屬性:

p = Person(20, 180)
print(p)
p()
print(p.__dict__)
p.__dict__['age']=22
print(p.__dict__)
p.weight = 60
print(p.__dict__)
print(dir(p))

執行輸出:

begin!!!
<__main__.Person object at 0x000002484557BCC8>
hello!!!
{'age': 20, 'height': 180}
{'age': 22, 'height': 180}
{'age': 22, 'height': 180, 'weight': 60}
['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'height', 'talk', 'weight']

  • 在實例創建之前調用__new__方法,返回值(實例)將傳遞給__init__方法的第一個參數。__new__方法的詳細介紹可參考:Python中的__new__和__init__
  • 實例化對象時會自動執行 __init__ 方法
  • 打印一個對象時,會自動執行__str__ 方法
  • 調用實例化對象時,會自動觸發__call__ 方法
  • 通過dir()方法可以打印出了對象p的屬性。

接下來測試一下其他反射函數:

callable()

if (callable(p)):
    print("p is callable")
else:
    print("p is not callable")

Out:

p is callable

isinstance()和type()

print(isinstance(p, Person))
print(type(p) == Person)
print(isinstance(p.age, int))
print(type(p.age) == int)

Out:

True
True
True
True

hasattr()

print(hasattr(p,"talk"))

print(hasattr(p.talk,"__call__"))

Out:

True
True

getattr()

print(getattr(p,"talk"))
print(getattr(p.talk, "__call__"))

if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")

print(getattr(p, "walk", None)) # 如果沒有walk屬性就返回None

Out:

<bound method Person.talk of <__main__.Person object at 0x000001FF52868288>>
<method-wrApper '__call__' of method object at 0x000001FF52155048>
I can't walk
None

setattr()

setattr(p,'walk','ON')
if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")
print(p.__dict__)

Out:

ON
{'age': 22, 'height': 180, 'weight': 60, 'walk': 'ON'}

delattr()

delattr(p,'walk')
if hasattr(p,'walk'):
    print(getattr(p,'walk'))
else:
    print("I can't walk")
print(p.__dict__)

Out:

I can't walk
{'age': 22, 'height': 180, 'weight': 60}

應用

下面介紹兩種Python反射的應用場景。

動態調用

從前面舉的例子中,我們了解到可以通過字符串來獲取對象的屬性(getattr()),這是非常有用的一個功能。比如,一個類中有很多方法,它們提供不同的服務,通過輸入的參數來判斷執行某個方法,一般的使用如下寫法:

class MyService():
    def service1(self):
        print("service1")

    def service2(self):
        print("service2")

    def service3(self):
        print("service3")

if __name__ == '__main__':
    Ser = MyService()
    s = input("請輸入您想要的服務: ").strip()
    if s == "service1":
        Ser.service1()
    elif s == "service2":
        Ser.service2()
    elif s == "service3":
        Ser.service3()
    else:
        print("error!")

如果函數比較少這樣寫沒有太大問題,如果有很多,這樣寫就比較復雜了,需要寫大量else語句,可以使用反射機制來寫:

if __name__ == '__main__':
    Ser = MyService()
    s = input("請輸入您想要的服務: ").strip()
    if hasattr(Ser, s):
        func = getattr(Ser, s)
        func()
    else:
        print("error!")

這樣是不是簡潔了很多,上面的例子中,通過反射,將字符串變成了函數,實現了對對象方法的動態調用。

動態屬性設置

可以通過setattr()方法進行動態屬性設置,在使用scapy庫構造報文時,我們需要設置某些報文字段,然而網絡協議的報文字段很多,在需要設置大量字段時,一個一個的賦值就很麻煩:

>>> ls(IP)
version    : BitField  (4 bits)                  = ('4')
ihl        : BitField  (4 bits)                  = ('None')
tos        : XByteField                          = ('0')
len        : ShortField                          = ('None')
id         : ShortField                          = ('1')
flags      : FlagsField                          = ('<Flag 0 ()>')
frag       : BitField  (13 bits)                 = ('0')
ttl        : ByteField                           = ('64')
proto      : ByteEnumField                       = ('0')
chksum     : XShortField                         = ('None')
src        : SourceIPField                       = ('None')
dst        : DestIPField                         = ('None')
options    : PacketListField                     = ('[]')

可以使用setattr()方法來賦值:

from scapy.all import *

fields = {"version":4, "src":"192.168.0.1","dst":"192.168.10.1"}
ip = IP()
for key, val in fields.items():
    setattr(ip, key, val)

分享到:
標簽:反射 Python
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定