17、python面向?qū)ο筮M階

面向?qū)ο筮M階

isinstance和issubclass

isinstance(obj,cls)檢查是否obj是否是類 cls 的對象

class Foo(object):

? ? pass?

obj = Foo()


isinstance(obj, Foo)

issubclass(sub, super)檢查sub類是否是 super 類的派生類?

class Foo(object):

? ? pass class Bar(Foo):

? ? pass

issubclass(Bar, Foo)

反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力(自?。_@一概念的提出很快引發(fā)了計算機科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語言的設(shè)計領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽儭?/p>


2 python面向?qū)ο笾械姆瓷洌和ㄟ^字符串的形式操作對象相關(guān)的屬性。python中的一切事物都是對象(都可以使用反射)

四個可以實現(xiàn)自省的函數(shù)

下列方法適用于類和對象(一切皆對象,類本身也是一個對象)

def hasattr(*args, **kwargs): # real signature unknown? ? """

? ? Return whether the object has an attribute with the given name.


? ? This is done by calling getattr(obj, name) and catching AttributeError.

? ? """? ? pass

以下實例展示了 hasattr 的使用方法:

#!/usr/bin/python# -*- coding: UTF-8 -*- class Coordinate:

? ? x = 10? ? y = -5? ? z = 0 point1 = Coordinate() print(hasattr(point1, 'x'))print(hasattr(point1, 'y'))print(hasattr(point1, 'z'))print(hasattr(point1, 'no'))? # 沒有該屬性

def getattr(object, name, default=None): # known special case of getattr? ? """

? ? getattr(object, name[, default]) -> value


? ? Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.

? ? When a default argument is given, it is returned when the attribute doesn't

? ? exist; without it, an exception is raised in that case.

? ? """? ? pass

以下實例展示了 getattr 的使用方法:

>>>class A(object):

...? ? bar = 1...

>>> a = A()>>> getattr(a, 'bar')? ? ? ? # 獲取屬性 bar 值1>>> getattr(a, 'bar2')? ? ? # 屬性 bar2 不存在,觸發(fā)異常Traceback (most recent call last):

? File "<stdin>", line 1, in <module>AttributeError: 'A' object has no attribute 'bar2'>>> getattr(a, 'bar2', 3)? ? # 屬性 bar2 不存在,但設(shè)置了默認值3

def setattr(x, y, v): # real signature unknown; restored from __doc__? ? """

? ? Sets the named attribute on the given object to the specified value.


? ? setattr(x, 'y', v) is equivalent to ``x.y = v''

? ? """? ? pass

以下實例展示了 setattr() 函數(shù)的使用方法:

實例一

>>>class A(object):

...? ? bar = 1...

>>> a = A()>>> getattr(a, 'bar')? ? ? ? ? # 獲取屬性 bar 值1>>> setattr(a, 'bar', 5)? ? ? # 設(shè)置屬性 bar 值>>> a.bar5

實例二

def delattr(x, y): # real signature unknown; restored from __doc__? ? """

? ? Deletes the named attribute from the given object.


? ? delattr(x, 'y') is equivalent to ``del x.y''

? ? """? ? pass

以下實例展示了 delattr 的使用方法:實例一class Coordinate:

? ? x = 10? ? y = -5? ? z = 0 point1 = Coordinate()

print('x = ',point1.x)print('y = ',point1.y)print('z = ',point1.z) delattr(Coordinate, 'z') print('--刪除 z 屬性后--')print('x = ',point1.x)print('y = ',point1.y) # 觸發(fā)錯誤print('z = ',point1.z)

實例二

class Foo:

? ? f = '類的靜態(tài)變量'? ? def __init__(self,name,age):

? ? ? ? self.name=name

? ? ? ? self.age=age

? ? def say_hi(self):

? ? ? ? print('hi,%s'%self.name)

obj=Foo('egon',73)#檢測是否含有某屬性print(hasattr(obj,'name'))print(hasattr(obj,'say_hi'))#獲取屬性n=getattr(obj,'name')print(n)

func=getattr(obj,'say_hi')

func()print(getattr(obj,'aaaaaaaa','不存在啊')) #報錯#設(shè)置屬性setattr(obj,'sb',True)

setattr(obj,'show_name',lambda self:self.name+'sb')print(obj.__dict__)print(obj.show_name(obj))#刪除屬性delattr(obj,'age')

delattr(obj,'show_name')

delattr(obj,'show_name111')#不存在,則報錯print(obj.__dict__)

實例三

class Foo(object):

? ? staticField = "old boy"

? ? def __init__(self):

? ? ? ? self.name = 'wupeiqi'

? ? def func(self):

? ? ? ? return 'func'

? ? @staticmethod

? ? def bar():

? ? ? ? return 'bar' print getattr(Foo, 'staticField')? #獲取到屬性值print getattr(Foo, 'func') #獲取到func的地址print getattr(Foo, 'bar')

實例四

import sys

def s1():

? ? print 's1'def s2():

? ? print 's2'this_module = sys.modules[__name__]

hasattr(this_module, 's1')

getattr(this_module, 's2')

導(dǎo)入其他模塊,利用反射查找該模塊是否存在某個方法

def test():

? ? print('from the test')

"""

程序目錄:

? ? module_test.py

? ? index.py

當前文件:

? ? index.py

"""import module_test as obj#obj.test()print(hasattr(obj,'test'))

getattr(obj,'test')()


__str__和__repr__

改變對象的字符串顯示__str__,__repr__

自定制格式化字符串__format__

#_*_coding:utf-8_*_format_dict={

? ? 'nat':'{obj.name}-{obj.addr}-{obj.type}',#學(xué)校名-學(xué)校地址-學(xué)校類型? ? 'tna':'{obj.type}:{obj.name}:{obj.addr}',#學(xué)校類型:學(xué)校名:學(xué)校地址? ? 'tan':'{obj.type}/{obj.addr}/{obj.name}',#學(xué)校類型/學(xué)校地址/學(xué)校名}class School:

? ? def __init__(self,name,addr,type):

? ? ? ? self.name=name

? ? ? ? self.addr=addr

? ? ? ? self.type=type

? ? def __repr__(self):

? ? ? ? return 'School(%s,%s)' %(self.name,self.addr)

? ? def __str__(self):

? ? ? ? return '(%s,%s)' %(self.name,self.addr)

? ? def __format__(self, format_spec):

? ? ? ? # if format_spec? ? ? ? if not format_spec or format_spec not in format_dict:

? ? ? ? ? ? format_spec='nat'? ? ? ? fmt=format_dict[format_spec]

? ? ? ? return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')print('from repr: ',repr(s1))print('from str: ',str(s1))print(s1)'''

str函數(shù)或者print函數(shù)--->obj.__str__()

repr或者交互式解釋器--->obj.__repr__()

如果__str__沒有被定義,那么就會使用__repr__來代替輸出

注意:這倆方法的返回值必須是字符串,否則拋出異常

'''print(format(s1,'nat'))print(format(s1,'tna'))print(format(s1,'tan'))print(format(s1,'asfdasdffd'))

class B:

? ? def __str__(self):

? ? ? ? return 'str : class B'? ? def __repr__(self):

? ? ? ? return 'repr : class B'b=B()print('%s'%b)print('%r'%b)


__del__

析構(gòu)方法,當對象在內(nèi)存中被釋放時,自動觸發(fā)執(zhí)行。

注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關(guān)心內(nèi)存的分配和釋放,因為此工作都是交給Python解釋器來執(zhí)行,所以,析構(gòu)函數(shù)的調(diào)用是由解釋器在進行垃圾回收時自動觸發(fā)執(zhí)行的。

class Foo:

? ? def __del__(self):

? ? ? ? print('執(zhí)行我啦')

f1=Foo()del f1print('------->')#輸出結(jié)果執(zhí)行我啦

------->



item系列

__getitem__\__setitem__\__delitem__

class Foo:

? ? def __init__(self,name):

? ? ? ? self.name=name

? ? def __getitem__(self, item):

? ? ? ? print(self.__dict__[item])

? ? def __setitem__(self, key, value):

? ? ? ? self.__dict__[key]=value

? ? ? ? print("f1['age']=18時,我執(zhí)行")

? ? def __delitem__(self, key):

? ? ? ? print('del obj[key]時,我執(zhí)行')

? ? ? ? self.__dict__.pop(key)

? ? def __delattr__(self, item):

? ? ? ? print('del obj.key時,我執(zhí)行')

? ? ? ? self.__dict__.pop(item)

f1=Foo('sb')

# __dict__[item] 內(nèi)部是以字典的形式保存數(shù)據(jù)

# __setitem__設(shè)置 key, value

f1['age']=18

f1['age1']=19

# __getitem__ 輸出設(shè)置的值

print(f1.age)?

# __delattr__ 根據(jù)Key刪除設(shè)置的屬性

del f1.age1

# __delitem__ 根據(jù)value刪除設(shè)置的屬性

del f1['age']

f1['name']='alex'

print(f1.__dict__)

__new__

View Code

class A:

? ? def __init__(self):

? ? ? ? self.x = 1

? ? ? ? print('in init function')

? ? def __new__(cls, *args, **kwargs):

? ? ? ? print('in new function')

? ? ? ? return object.__new__(A, *args, **kwargs)

a = A()

print(a.x)

單例模式

class Singleton:

? ? def __new__(cls, *args, **kw):

? ? ? ? if not hasattr(cls, '_instance'):

? ? ? ? ? ? cls._instance = object.__new__(cls, *args, **kw)

? ? ? ? return cls._instance

one = Singleton()

two = Singleton()

two.a = 3print(one.a)# 3

# one和two完全相同,可以用id(), ==, is檢測print(id(one))# 29097904print(id(two))# 29097904print(one == two)# Trueprint(one is two)


__call__

對象后面加括號,觸發(fā)執(zhí)行。

注:構(gòu)造方法的執(zhí)行是由創(chuàng)建對象觸發(fā)的,即:對象 = 類名() ;而對于 __call__ 方法的執(zhí)行是由對象后加括號觸發(fā)的,即:對象() 或者 類()()

class Foo:

? ? def __init__(self):

? ? ? ? pass? ?

? ? def __call__(self, *args, **kwargs):

? ? ? ? print('__call__')

obj = Foo() # 執(zhí)行 __init__obj()? ? ? # 執(zhí)行 __call__


__len__

class A:

? ? def __init__(self):

? ? ? ? self.a = 1

? ? ? ? self.b = 2

? ? def __len__(self):

? ? ? ? return len(self.__dict__)

a = A()print(len(a))


__hash__

class A:

? ? def __init__(self):

? ? ? ? self.a = 1

? ? ? ? self.b = 2

? ? def __hash__(self):

? ? ? ? return hash(str(self.a)+str(self.b))

a = A()print(hash(a))


__eq__

class A:

? ? def __init__(self):

? ? ? ? self.a = 1

? ? ? ? self.b = 2

? ? def __eq__(self,obj):

? ? ? ? if? self.a == obj.a and self.b == obj.b:

? ? ? ? ? ? return True

a = A()

b = A()print(a == b)


紙牌游戲

from collections import namedtuple

Card = namedtuple('Card',['rank','suit'])

class FranchDeck:

? ? ranks = [str(n) for n in range(2,11)] + list('JQKA')

? ? suits = ['紅心','方板','梅花','黑桃']

? ? def __init__(self):

? ? ? ? self._cards = [Card(rank,suit) for rank in FranchDeck.ranks

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for suit in FranchDeck.suits]

? ? def __len__(self):

? ? ? ? return len(self._cards)

? ? def __getitem__(self, item):

? ? ? ? return self._cards[item]

deck = FranchDeck()print(deck[0])from random import choiceprint(choice(deck))print(choice(deck))

紙牌游戲2

from collections import namedtuple

Card = namedtuple('Card',['rank','suit'])

class FranchDeck:

? ? ranks = [str(n) for n in range(2,11)] + list('JQKA')

? ? suits = ['紅心','方板','梅花','黑桃']

? ? def __init__(self):

? ? ? ? self._cards = [Card(rank,suit) for rank in FranchDeck.ranks

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for suit in FranchDeck.suits]

? ? def __len__(self):

? ? ? ? return len(self._cards)

? ? def __getitem__(self, item):

? ? ? ? return self._cards[item]

? ? def __setitem__(self, key, value):

? ? ? ? self._cards[key] = value

deck = FranchDeck()

print(deck[0])

from random import choice

print(choice(deck))

print(choice(deck))

from random import shuffle

shuffle(deck)

print(deck[:5])

一道面試題

class Person:

? ? def __init__(self,name,age,sex):

? ? ? ? self.name = name

? ? ? ? self.age = age

? ? ? ? self.sex = sex

? ? def __hash__(self):

? ? ? ? return hash(self.name+self.sex)

? ? def __eq__(self, other):

? ? ? ? if self.name == other.name and self.sex == other.sex:return True

p_lst = []for i in range(84):

? ? p_lst.append(Person('egon',i,'male'))print(p_lst)print(set(p_lst))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容