Python: 學習系列之六:對象的內置函數及類對象的特殊方法

系列

issubclass()與isinstance() 判斷類對象與類對象或實例的關係

class ParentClass(object):
    pass


class ChildClass(ParentClass):
    pass


class ThirdClass(object):
    pass


# issubclass判斷類對象與類對象的關係
print(issubclass(ChildClass, ParentClass))  # True
print(issubclass(ChildClass, (ParentClass, ThirdClass)))  # True,後面是個元組,只要滿足元組內任意一個父類就爲True

# isinstance判斷實例對象與類對象的關係
c = ChildClass()
print(isinstance(c, ChildClass))  # True
print(isinstance(c, (ChildClass, ParentClass, ThirdClass)))  # True,後面是個元組,只要滿足元組內任意一個類就爲True

type()獲取指定對象的類型

print(type(c)) #<class '__main__.ChildClass'>,獲取指定對象的類型
print(type(ChildClass)) #<class 'type'>, 類對象的類型是type

dir()獲取對象的所有信息和__dict__獲取對象自定義信息

class MyClass(object):
    def __init__(self):
        self.name = 'cong'

    @classmethod
    def cm(cls):
        pass

    @staticmethod
    def sm(p1):
        print(p1)


#  獲取所有屬性和方法,類對象結果中不包含實例屬性
print(dir(MyClass))  # [...'__subclasshook__', '__weakref__', 'cm'] 獲取所有屬性和方法

# 獲取所有屬性和方法, ['__subclasshook__','__weakref__', 'cm', 'name', 'sm']]
print(dir(MyClass()))

# 獲取自定義屬性和方法
# {'cm': <classmethod object at 0x000002266E1B5710>, 'sm': <staticmethod object at 0x000002266E1B5748>}
print(MyClass.__dict__)
# 獲取自定義屬性和方法
print(MyClass().__dict__)  # {'name': 'cong'}

反射(hasattr,getattr,setattr,delattr)

"""
    用於反射,當不知道對象屬性或方法的情況下適用
    1. hasattr(object,name) 用於判斷對象是否有指定的屬性或方法
    2. getattr(object,name[,default]) 用於獲取指定屬性的值或方法,getattr(object,name)等價於object.name
    3. setattr(object,name,value) 給對象添加或修改指定屬性的值或方法,setattr(object,name,value)等價於object.name=value
    4. delattr(object,name) 用於刪除指定的屬性或方法,等價於del object.name
"""


class MyClass(object):
    def __init__(self):
        self.x = 1

    def do_sth(self):
        print('do_sth has been called')


mc = MyClass()
# hasattr 用於判斷對象是否有指定的屬性或方法
print(hasattr(mc, 'x'))  # True

print(hasattr(mc, 'do_sth'))  # True
print(hasattr(mc, 'Y'))  # False

print(getattr(mc, 'x'))  # 1
print(getattr(mc, 'Y', 2))  # 2
# <bound method MyClass.do_sth of <__main__.MyClass object at 0x0000020B74C06668>>
print(getattr(mc, 'do_sth'))

# 方法獲取後,這裏可以直接調用
f = getattr(mc, 'do_sth')
f()  # do_sth has been called

setattr(mc, 'x', 6)
print(mc.x)  # 6
print(getattr(mc,'x'))  # 6


delattr(mc,'x')
print(hasattr(mc, 'x'))  # False

len()返回對象的長度 及__len__()

print(len('abc'))  # 3
print(len([1, 2, 3]))  # 3
print(len((1, 2, 3)))  # 3
print(len({'a': 1, 'b': 2, 'c': 3}))  # 3


class MyClass(object):
    def __len__(self):
        return 18


# 只有實現了__len__方法的自定義對象,才能使用len(MyClass())就會報錯
print(len(MyClass()))  # 18

__iter()和__next() 自定義迭代器

"""
    自定義迭代器,如果想讓for-in語句可以用於自定義類對象的實例對象,必須要實現__iter__()和__next()這兩個方法。
    for-in語句會首先調用__iter_()返回一個可迭代的對象,然後不斷調用__next__()返回下一次迭代的值,直到拋出StopIteration時退出循環
"""


class MyClass(object):
    def __init__(self):
        self.i = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.i > 5:
            raise StopIteration()
        else:
            self.i += 1
            return self.i


for key in MyClass():
    print(key)  # 1,2,3,4,5,6

__add__()和__radd__() 讓兩個對象相加,即obj1+obj2

"""
    1. + 對應的特殊方法是__add__()和__radd__()
    2. - 對應的特殊方法是__sub__()和__rsub__()
    3. * 對應的特殊方法是__mul__()和__rmul__()
    4. / 對應的特殊方法是__truediv__()和__rtruediv__()
    5. // 對應的特殊方法是__floordiv__()和__rfloordiv__()
"""


class MyClass1(object):
    def __add__(self, other):
        print('add have been called')
        return 'x' + other


class MyClass2(object):
    def __radd__(self, other):
        print('radd have been called')
        return other+'y'


# add have been called
# radd have been called
# xy
print(MyClass1()+MyClass2())

__str__() 和__repr()都返回對象的字符串表示

class MyClass(object):
    def __str__(self):
        return 'x'

    def __repr__(self):
        return 'y'


print(str(MyClass()))  # x
print(repr(MyClass()))  # y

# hello
# world
print(str('hello \n world'))  # 這是給用戶看的
print(repr('hello \n world'))  # 'hello \n world', 這是給程序員看的,主要用於調試用的

__new__() 創建實例對象

"""
    當使用"類名([實參])"創建實例對象時,python解析器的主要處理過程包括兩步:
    1. 調用特殊方法__new__()創建實例對象
    2. 調用特殊方法__init__()對對象的實例進行初始化

    如果__new__()沒有定義,就會調用父類中的__new__(),直到找到object中的__new__().
"""


class ParentClass(object):
    def __new__(cls):
        obj = super().__new__(cls)
        print("the object has been created , the id is %s" % id(obj))
        return obj


class ChildClass(ParentClass):
    def __init__(self):
        print("the object has been initialize, the id is %s" % id(self))


# the object has been created, the id is 1897583171176
# the object has been initialize, the id is 1897583171176
c = ChildClass()

# 從上可以看出,它的id是一樣的,c這個實例對象實例上是由object中的__new__()方式來創建的。

__del__() 對象被銷燬之前,會自動調用__del__()來執行一些額外的清理工作

"""
    對象被銷燬之前,會自動調用__del__()來執行一些額外的清理工作
    當對象的引用計數爲0時,對象並不會被立即回收,何時收回並不確定
"""
class MyClass(object):
    def __del__(self):
        print('the object will be deleted!')


mc = MyClass()
del mc  # the object will be deleted!

__getattribute__() 避免指定的屬性或方法不存在時拋出AttributeError,可以使用__getattr__()或__getattribute__()

"""
    當訪問實例對象的屬性或方法時,如果指定的屬性或方法不存在時,就分拋出AttributeError.
    爲了避免指定的屬性或方法不存時拋出如上錯誤,可以使用__getattribute__()或者__getattr__()
"""
class MyClass(object):
    def __getattribute__(self,name):
        if name == "data":
            return 18
        else:
            raise AttributeError("Not Found")

mc = MyClass()
print(mc.data)

__getitem__() ,__setitem__(),delitem__()讓實例可以實現類似這樣的功能o=obj[key], obj[key]=value或del obj[key]

class MyClass(object):
    def __init__(self):
        self.data = {}

    def __getitem__(self, key):
        return self.data[key]

    def __setitem__(self, key, value):
        self.data[key] = value

    def __delitem__(self, key):
        del self.data[key]


mc = MyClass()
mc['name'] = 'cong'
mc['age'] = 18
print(mc.data)   # {'name': 'cong', 'age': 18}
print(mc.data['name'])  # cong
del mc['age']
print(mc.data)  # {'name': 'cong'}

__call__() 可以像調用函數一樣調用實例

class MyClass(object):
    def __call__(self, *args, **kwargs):
        print(args, kwargs)


mc = MyClass()
mc()  # () {}
mc(1, 2, x=3, y=4) #(1, 2) {'x': 3, 'y': 4}

print(callable(print)) #True
print(callable(mc))  # True

特殊屬性__doc__,用於表示類對象的文檔字符串

def test():
    """This is a test document string.

    This is the detailed information
    """
    pass



print(test.__doc__)  # This is a test document string.

# Help on function test in module __main__:
# test()
# This is a test document string
# None
print(help(test))

特殊屬性__slots__ 可以動態綁定屬性和方法


"""
    默認情況下,訪問實例對象的屬性是通過訪問特殊屬性__dict__來實現的,比如:訪問obj.x 其實是訪問obj.__dict__['x']
    當在對象中定義了特殊屬性__slots__後,其實對象就不再創建特殊屬性__dict__, #AttributeError: 'MyClass' object has no attribute '__dict__'
    __slots__只對當前對象起作用,對其子類是不起作用的,如果子類中也定義了__slots__,它子類動態綁定的內容爲子類的slots+父類的slots
"""

from types import MethodType


class MyClass(object):
    # 這裏可以賦值一個所有元素都是字符串的數組或元組
    __slots__ = ("attr1", "do_sth1")


mc = MyClass()
mc.attr1 = 20
# mc.att2 = 23  # AttributeError: 'MyClass' object has no attribute 'att2'


def do_sth1(self):
    print('do_sth1 has been called')


mc.do_sth1 = MethodType(do_sth1, mc)

mc.do_sth1()  # do_sth1 has been called

print(mc.__dict__)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章