面向對象進階

閱讀目錄

  • isinstance和issubclass
  • 反射
    •   setattr
    •   delattr
    •   getattr
    •   hasattr
  • __str__和__repr__
  • item系列
    •   __getitem__
    •   __setitem__
    •   __delitem__
  • __del__
  • __new__
  • __call__
  • with和__enter__,__exit__
  • __len__
  • __hash__
  • __eq__
 

isinstance和issubclass

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

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年首次提出的,主要是指程序能夠訪問、檢測和修改它自己狀態或行爲的一種能力(自省)。這一律唸的提出很快引起了計算機科學領域關於應用反射性的研究。它首先被程序語言的設計領域所採用,並在Lisp和麪向對象方面取得了成績。app

 

2 python面向對象中的反射:經過字符串的形式操做對象相關的屬性。python中的一切事物都是對象(均可以使用反射)dom

四個能夠實現自省的函數函數

下列方法適用於類和對象(一切皆對象,類自己也是一個對象)post

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.
"""
passui

hasattrthis

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.
"""
passspa

getattr

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

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 Foo:
f = '類的靜態變量'
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','不存在啊')) #報錯

#設置屬性
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')
print getattr(Foo, 'bar')

類也是對象

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys


def s1():
print 's1'


def s2():
print 's2'


this_module = sys.modules[__name__]

hasattr(this_module, 's1')
getattr(this_module, 's2')

反射當前模塊成員

導入其餘模塊,利用反射查找該模塊是否存在某個方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def test():
    print('from the test')

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
程序目錄:
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}',#學校名-學校地址-學校類型
'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校類型:學校名:學校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校類型/學校地址/學校名
}
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函數或者print函數--->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)

%s和%r

 

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
def __delitem__(self, key):
print('del obj[key]時,我執行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key時,我執行')
self.__dict__.pop(item)

f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)

__del__

析構方法,當對象在內存中被釋放時,自動觸發執行。

注:此方法通常無須定義,由於Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,由於此工做都是交給Python解釋器來執行,因此,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。

class Foo:

def __del__(self):
print('執行我啦')

f1=Foo()
del f1
print('------->')

#輸出結果
執行我啦
------->

簡單示範

 

__new__

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)

a = A()
print(a.x)

class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance

one = Singleton()
two = Singleton()

two.a = 3
print(one.a)
# 3
# one和two徹底相同,能夠用id(), ==, is檢測
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)

單例模式

單例模式

 

__call__

對象後面加括號,觸發執行。

注:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()

class Foo:

def __init__(self):
pass

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

print('__call__')


obj = Foo() # 執行 __init__
obj() # 執行 __call__

 

with和__enter__,__exit__

class A:
def __enter__(self):
print('before')

def __exit__(self, exc_type, exc_val, exc_tb):
print('after')


with A() as a:
print('123')

with語句

class A:
def __init__(self):
print('init')

def __enter__(self):
print('before')

def __exit__(self, exc_type, exc_val, exc_tb):
print('after')


with A() as a:
print('123')

with語句和init

class Myfile:
def __init__(self,path,mode='r',encoding = 'utf-8'):
self.path = path
self.mode = mode
self.encoding = encoding

def __enter__(self):
self.f = open(self.path, mode=self.mode, encoding=self.encoding)
return self.f

def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()


with Myfile('file',mode='w') as f:
f.write('wahaha')

with和文件操做

import pickle
class MyPickledump:
def __init__(self,path):
self.path = path

def __enter__(self):
self.f = open(self.path, mode='ab')
return self

def dump(self,content):
pickle.dump(content,self.f)

def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()

class Mypickleload:
def __init__(self,path):
self.path = path

def __enter__(self):
self.f = open(self.path, mode='rb')
return self


def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()

def load(self):
return pickle.load(self.f)


def loaditer(self):
while True:
try:
yield self.load()
except EOFError:
break

 

# with MyPickledump('file') as f:
# f.dump({1,2,3,4})

with Mypickleload('file') as f:
for item in f.loaditer():
print(item)

with和pickle

import pickle
class MyPickledump:
def __init__(self,path):
self.path = path

def __enter__(self):
self.f = open(self.path, mode='ab')
return self

def dump(self,content):
pickle.dump(content,self.f)

def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()

class Mypickleload:
def __init__(self,path):
self.path = path

def __enter__(self):
self.f = open(self.path, mode='rb')
return self


def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()

def __iter__(self):
while True:
try:
yield pickle.load(self.f)
except EOFError:
break

 

# with MyPickledump('file') as f:
# f.dump({1,2,3,4})

with Mypickleload('file') as f:
for item in f:
print(item)

with和pickle和iter

 

__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)

 

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 choice
print(choice(deck))
print(choice(deck))

紙牌遊戲

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])

紙牌遊戲2

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))

一道面試題

相關文章
相關標籤/搜索