1.1.鴨子類型和多態
“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。”
我們並不關心對象是什么類型,到底是不是鴨子,只關心行為。
實例一:
# 鴨子類型和多態簡單實例 class Dog(object): def say(self): print('a dog') class Cat(object): def say(self): print('a cat') class Duck(object): def say(self): print('a duck') animal_list = [Dog,Cat,Duck] for animal in animal_list: animal().say() #運行結果 a dog a cat a duck
實例二:
類只要實現了__getitem__方法,它就是可迭代的,並不關心對象的本身,只關心行為,然后就可以當做extend的參數。
class Company(object): def __init__(self, employee_list): self.employee = employee_list def __getitem__(self, item): return self.employee[item] company = Company(["11", "22", "33"]) a = ['derek1','derek2'] name_set = set() name_set.add('tom1') name_set.add(('tom2')) #extend里面的參數介紹 #def extend(self, iterable): # real signature unknown; restored from __doc__ #""" L.extend(iterable) -> None -- extend list by appending elements from the iterable """ #extend里面可以添加任何可迭代的參數,給類添加一個魔法函數__getitem__,類就變成可迭代的,所以可以extend進去 a.extend(company) print(a) #['derek1', 'derek2', '11', '22', '33'] a.extend(name_set) print(a) #['derek1', 'derek2', '11', '22', '33', 'tom2', 'tom1']
1.2.抽象基類(abc模塊)
抽象基類的作用類似於JAVA中的接口。在接口中定義各種方法,然后繼承接口的各種類進行具體方法的實現。抽象基類就是定義各種方法而不做具體實現的類,任何繼承自抽象基類的類必須實現這些方法,否則無法實例化
(1)判斷類時候有某種屬性
#判斷類是否有某種屬性 class Company(object): def __init__(self, employee_list): self.employee = employee_list def __len__(self): return len(self.employee) com = Company(["11", "22", "33"]) #hasattr判斷類有沒有某種屬性,方法也是類的屬性 print(hasattr(com,"__len__")) #True #雖然用hasattr可以判斷,但正確的方式是定義一個抽象基類 #我們在某些情況下希望判定某個對象的類型,可以用抽象基類 from collections.abc import Sized print(isinstance(com,Sized)) #True # print(len(com))
class Sized(metaclass=ABCMeta): __slots__ = () @abstractmethod def __len__(self): return 0 @classmethod def __subclasshook__(cls, C): if cls is Sized: return _check_methods(C, "__len__") return NotImplemented
(2)abc模塊
簡單抽象基類實例
#模擬一個抽象基類 #寫一個抽象基類,它的子類必須要重寫抽象基類里面的方法 import abc #定義一個抽象基類 class CacheBase(metaclass=abc.ABCMeta): @abc.abstractclassmethod def get(self,key): pass @abc.abstractclassmethod def set(self,key,value): pass #子類,必須有抽象基類里面的方法,get和set #假入不寫set方法會報錯 class RedisCache(CacheBase): def get(self,key): pass # def set(self,key,value): # pass redis_cache = RedisCache()
#模擬一個抽象基類 #寫一個抽象基類,它的子類必須要重寫抽象基類里面的方法 import abc #定義一個抽象基類 class CacheBase(metaclass=abc.ABCMeta): @abc.abstractclassmethod def get(self,key): pass @abc.abstractclassmethod def set(self,key,value): pass #子類,必須有抽象基類里面的方法,get和set #假入不寫set方法會報錯 class RedisCache(CacheBase): def get(self,key): pass def set(self,key,value): pass redis_cache = RedisCache()

(3)abc里面所有的抽象基類
from collections.abc import *
所有的抽象基類
# Copyright 2007 Google, Inc. All Rights Reserved. # Licensed to PSF under a Contributor Agreement. """Abstract Base Classes (ABCs) for collections, according to PEP 3119. Unit tests are in test_collections. """ from abc import ABCMeta, abstractmethod import sys __all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", "AsyncGenerator", "Hashable", "Iterable", "Iterator", "Generator", "Reversible", "Sized", "Container", "Callable", "Collection", "Set", "MutableSet", "Mapping", "MutableMapping", "MappingView", "KeysView", "ItemsView", "ValuesView", "Sequence", "MutableSequence", "ByteString", ] # This module has been renamed from collections.abc to _collections_abc to # speed up interpreter startup. Some of the types such as MutableMapping are # required early but collections module imports a lot of other modules. # See issue #19218 __name__ = "collections.abc" # Private list of types that we want to register with the various ABCs # so that they will pass tests like: # it = iter(somebytearray) # assert isinstance(it, Iterable) # Note: in other implementations, these types might not be distinct # and they may have their own implementation specific types that # are not included on this list. bytes_iterator = type(iter(b'')) bytearray_iterator = type(iter(bytearray())) #callable_iterator = ??? dict_keyiterator = type(iter({}.keys())) dict_valueiterator = type(iter({}.values())) dict_itemiterator = type(iter({}.items())) list_iterator = type(iter([])) list_reverseiterator = type(iter(reversed([]))) range_iterator = type(iter(range(0))) longrange_iterator = type(iter(range(1 << 1000))) set_iterator = type(iter(set())) str_iterator = type(iter("")) tuple_iterator = type(iter(())) zip_iterator = type(iter(zip())) ## views ## dict_keys = type({}.keys()) dict_values = type({}.values()) dict_items = type({}.items()) ## misc ## mappingproxy = type(type.__dict__) generator = type((lambda: (yield))()) ## coroutine ## async def _coro(): pass _coro = _coro() coroutine = type(_coro) _coro.close() # Prevent ResourceWarning del _coro ## asynchronous generator ## async def _ag(): yield _ag = _ag() async_generator = type(_ag) del _ag ### ONE-TRICK PONIES ### def _check_methods(C, *methods): mro = C.__mro__ for method in methods: for B in mro: if method in B.__dict__: if B.__dict__[method] is None: return NotImplemented break else: return NotImplemented return True class Hashable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __hash__(self): return 0 @classmethod def __subclasshook__(cls, C): if cls is Hashable: return _check_methods(C, "__hash__") return NotImplemented class Awaitable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __await__(self): yield @classmethod def __subclasshook__(cls, C): if cls is Awaitable: return _check_methods(C, "__await__") return NotImplemented class Coroutine(Awaitable): __slots__ = () @abstractmethod def send(self, value): """Send a value into the coroutine. Return next yielded value or raise StopIteration. """ raise StopIteration @abstractmethod def throw(self, typ, val=None, tb=None): """Raise an exception in the coroutine. Return next yielded value or raise StopIteration. """ if val is None: if tb is None: raise typ val = typ() if tb is not None: val = val.with_traceback(tb) raise val def close(self): """Raise GeneratorExit inside coroutine. """ try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("coroutine ignored GeneratorExit") @classmethod def __subclasshook__(cls, C): if cls is Coroutine: return _check_methods(C, '__await__', 'send', 'throw', 'close') return NotImplemented Coroutine.register(coroutine) class AsyncIterable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __aiter__(self): return AsyncIterator() @classmethod def __subclasshook__(cls, C): if cls is AsyncIterable: return _check_methods(C, "__aiter__") return NotImplemented class AsyncIterator(AsyncIterable): __slots__ = () @abstractmethod async def __anext__(self): """Return the next item or raise StopAsyncIteration when exhausted.""" raise StopAsyncIteration def __aiter__(self): return self @classmethod def __subclasshook__(cls, C): if cls is AsyncIterator: return _check_methods(C, "__anext__", "__aiter__") return NotImplemented class AsyncGenerator(AsyncIterator): __slots__ = () async def __anext__(self): """Return the next item from the asynchronous generator. When exhausted, raise StopAsyncIteration. """ return await self.asend(None) @abstractmethod async def asend(self, value): """Send a value into the asynchronous generator. Return next yielded value or raise StopAsyncIteration. """ raise StopAsyncIteration @abstractmethod async def athrow(self, typ, val=None, tb=None): """Raise an exception in the asynchronous generator. Return next yielded value or raise StopAsyncIteration. """ if val is None: if tb is None: raise typ val = typ() if tb is not None: val = val.with_traceback(tb) raise val async def aclose(self): """Raise GeneratorExit inside coroutine. """ try: await self.athrow(GeneratorExit) except (GeneratorExit, StopAsyncIteration): pass else: raise RuntimeError("asynchronous generator ignored GeneratorExit") @classmethod def __subclasshook__(cls, C): if cls is AsyncGenerator: return _check_methods(C, '__aiter__', '__anext__', 'asend', 'athrow', 'aclose') return NotImplemented AsyncGenerator.register(async_generator) class Iterable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __iter__(self): while False: yield None @classmethod def __subclasshook__(cls, C): if cls is Iterable: return _check_methods(C, "__iter__") return NotImplemented class Iterator(Iterable): __slots__ = () @abstractmethod def __next__(self): 'Return the next item from the iterator. When exhausted, raise StopIteration' raise StopIteration def __iter__(self): return self @classmethod def __subclasshook__(cls, C): if cls is Iterator: return _check_methods(C, '__iter__', '__next__') return NotImplemented Iterator.register(bytes_iterator) Iterator.register(bytearray_iterator) #Iterator.register(callable_iterator) Iterator.register(dict_keyiterator) Iterator.register(dict_valueiterator) Iterator.register(dict_itemiterator) Iterator.register(list_iterator) Iterator.register(list_reverseiterator) Iterator.register(range_iterator) Iterator.register(longrange_iterator) Iterator.register(set_iterator) Iterator.register(str_iterator) Iterator.register(tuple_iterator) Iterator.register(zip_iterator) class Reversible(Iterable): __slots__ = () @abstractmethod def __reversed__(self): while False: yield None @classmethod def __subclasshook__(cls, C): if cls is Reversible: return _check_methods(C, "__reversed__", "__iter__") return NotImplemented class Generator(Iterator): __slots__ = () def __next__(self): """Return the next item from the generator. When exhausted, raise StopIteration. """ return self.send(None) @abstractmethod def send(self, value): """Send a value into the generator. Return next yielded value or raise StopIteration. """ raise StopIteration @abstractmethod def throw(self, typ, val=None, tb=None): """Raise an exception in the generator. Return next yielded value or raise StopIteration. """ if val is None: if tb is None: raise typ val = typ() if tb is not None: val = val.with_traceback(tb) raise val def close(self): """Raise GeneratorExit inside generator. """ try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("generator ignored GeneratorExit") @classmethod def __subclasshook__(cls, C): if cls is Generator: return _check_methods(C, '__iter__', '__next__', 'send', 'throw', 'close') return NotImplemented Generator.register(generator) class Sized(metaclass=ABCMeta): __slots__ = () @abstractmethod def __len__(self): return 0 @classmethod def __subclasshook__(cls, C): if cls is Sized: return _check_methods(C, "__len__") return NotImplemented class Container(metaclass=ABCMeta): __slots__ = () @abstractmethod def __contains__(self, x): return False @classmethod def __subclasshook__(cls, C): if cls is Container: return _check_methods(C, "__contains__") return NotImplemented class Collection(Sized, Iterable, Container): __slots__ = () @classmethod def __subclasshook__(cls, C): if cls is Collection: return _check_methods(C, "__len__", "__iter__", "__contains__") return NotImplemented class Callable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __call__(self, *args, **kwds): return False @classmethod def __subclasshook__(cls, C): if cls is Callable: return _check_methods(C, "__call__") return NotImplemented ### SETS ### class Set(Collection): """A set is a finite, iterable container. This class provides concrete generic implementations of all methods except for __contains__, __iter__ and __len__. To override the comparisons (presumably for speed, as the semantics are fixed), redefine __le__ and __ge__, then the other operations will automatically follow suit. """ __slots__ = () def __le__(self, other): if not isinstance(other, Set): return NotImplemented if len(self) > len(other): return False for elem in self: if elem not in other: return False return True def __lt__(self, other): if not isinstance(other, Set): return NotImplemented return len(self) < len(other) and self.__le__(other) def __gt__(self, other): if not isinstance(other, Set): return NotImplemented return len(self) > len(other) and self.__ge__(other) def __ge__(self, other): if not isinstance(other, Set): return NotImplemented if len(self) < len(other): return False for elem in other: if elem not in self: return False return True def __eq__(self, other): if not isinstance(other, Set): return NotImplemented return len(self) == len(other) and self.__le__(other) @classmethod def _from_iterable(cls, it): '''Construct an instance of the class from any iterable input. Must override this method if the class constructor signature does not accept an iterable for an input. ''' return cls(it) def __and__(self, other): if not isinstance(other, Iterable): return NotImplemented return self._from_iterable(value for value in other if value in self) __rand__ = __and__ def isdisjoint(self, other): 'Return True if two sets have a null intersection.' for value in other: if value in self: return False return True def __or__(self, other): if not isinstance(other, Iterable): return NotImplemented chain = (e for s in (self, other) for e in s) return self._from_iterable(chain) __ror__ = __or__ def __sub__(self, other): if not isinstance(other, Set): if not isinstance(other, Iterable): return NotImplemented other = self._from_iterable(other) return self._from_iterable(value for value in self if value not in other) def __rsub__(self, other): if not isinstance(other, Set): if not isinstance(other, Iterable): return NotImplemented other = self._from_iterable(other) return self._from_iterable(value for value in other if value not in self) def __xor__(self, other): if not isinstance(other, Set): if not isinstance(other, Iterable): return NotImplemented other = self._from_iterable(other) return (self - other) | (other - self) __rxor__ = __xor__ def _hash(self): """Compute the hash value of a set. Note that we don't define __hash__: not all sets are hashable. But if you define a hashable set type, its __hash__ should call this function. This must be compatible __eq__. All sets ought to compare equal if they contain the same elements, regardless of how they are implemented, and regardless of the order of the elements; so there's not much freedom for __eq__ or __hash__. We match the algorithm used by the built-in frozenset type. """ MAX = sys.maxsize MASK = 2 * MAX + 1 n = len(self) h = 1927868237 * (n + 1) h &= MASK for x in self: hx = hash(x) h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 h &= MASK h = h * 69069 + 907133923 h &= MASK if h > MAX: h -= MASK + 1 if h == -1: h = 590923713 return h Set.register(frozenset) class MutableSet(Set): """A mutable set is a finite, iterable container. This class provides concrete generic implementations of all methods except for __contains__, __iter__, __len__, add(), and discard(). To override the comparisons (presumably for speed, as the semantics are fixed), all you have to do is redefine __le__ and then the other operations will automatically follow suit. """ __slots__ = () @abstractmethod def add(self, value): """Add an element.""" raise NotImplementedError @abstractmethod def discard(self, value): """Remove an element. Do not raise an exception if absent.""" raise NotImplementedError def remove(self, value): """Remove an element. If not a member, raise a KeyError.""" if value not in self: raise KeyError(value) self.discard(value) def pop(self): """Return the popped value. Raise KeyError if empty.""" it = iter(self) try: value = next(it) except StopIteration: raise KeyError self.discard(value) return value def clear(self): """This is slow (creates N new iterators!) but effective.""" try: while True: self.pop() except KeyError: pass def __ior__(self, it): for value in it: self.add(value) return self def __iand__(self, it): for value in (self - it): self.discard(value) return self def __ixor__(self, it): if it is self: self.clear() else: if not isinstance(it, Set): it = self._from_iterable(it) for value in it: if value in self: self.discard(value) else: self.add(value) return self def __isub__(self, it): if it is self: self.clear() else: for value in it: self.discard(value) return self MutableSet.register(set) ### MAPPINGS ### class Mapping(Collection): __slots__ = () """A Mapping is a generic container for associating key/value pairs. This class provides concrete generic implementations of all methods except for __getitem__, __iter__, and __len__. """ @abstractmethod def __getitem__(self, key): raise KeyError def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default def __contains__(self, key): try: self[key] except KeyError: return False else: return True def keys(self): "D.keys() -> a set-like object providing a view on D's keys" return KeysView(self) def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self) def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self) def __eq__(self, other): if not isinstance(other, Mapping): return NotImplemented return dict(self.items()) == dict(other.items()) __reversed__ = None Mapping.register(mappingproxy) class MappingView(Sized): __slots__ = '_mapping', def __init__(self, mapping): self._mapping = mapping def __len__(self): return len(self._mapping) def __repr__(self): return '{0.__class__.__name__}({0._mapping!r})'.format(self) class KeysView(MappingView, Set): __slots__ = () @classmethod def _from_iterable(self, it): return set(it) def __contains__(self, key): return key in self._mapping def __iter__(self): yield from self._mapping KeysView.register(dict_keys) class ItemsView(MappingView, Set): __slots__ = () @classmethod def _from_iterable(self, it): return set(it) def __contains__(self, item): key, value = item try: v = self._mapping[key] except KeyError: return False else: return v is value or v == value def __iter__(self): for key in self._mapping: yield (key, self._mapping[key]) ItemsView.register(dict_items) class ValuesView(MappingView): __slots__ = () def __contains__(self, value): for key in self._mapping: v = self._mapping[key] if v is value or v == value: return True return False def __iter__(self): for key in self._mapping: yield self._mapping[key] ValuesView.register(dict_values) class MutableMapping(Mapping): __slots__ = () """A MutableMapping is a generic container for associating key/value pairs. This class provides concrete generic implementations of all methods except for __getitem__, __setitem__, __delitem__, __iter__, and __len__. """ @abstractmethod def __setitem__(self, key, value): raise KeyError @abstractmethod def __delitem__(self, key): raise KeyError __marker = object() def pop(self, key, default=__marker): '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. ''' try: value = self[key] except KeyError: if default is self.__marker: raise return default else: del self[key] return value def popitem(self): '''D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty. ''' try: key = next(iter(self)) except StopIteration: raise KeyError value = self[key] del self[key] return key, value def clear(self): 'D.clear() -> None. Remove all items from D.' try: while True: self.popitem() except KeyError: pass def update(*args, **kwds): ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v ''' if not args: raise TypeError("descriptor 'update' of 'MutableMapping' object " "needs an argument") self, *args = args if len(args) > 1: raise TypeError('update expected at most 1 arguments, got %d' % len(args)) if args: other = args[0] if isinstance(other, Mapping): for key in other: self[key] = other[key] elif hasattr(other, "keys"): for key in other.keys(): self[key] = other[key] else: for key, value in other: self[key] = value for key, value in kwds.items(): self[key] = value def setdefault(self, key, default=None): 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' try: return self[key] except KeyError: self[key] = default return default MutableMapping.register(dict) ### SEQUENCES ### class Sequence(Reversible, Collection): """All the operations on a read-only sequence. Concrete subclasses must override __new__ or __init__, __getitem__, and __len__. """ __slots__ = () @abstractmethod def __getitem__(self, index): raise IndexError def __iter__(self): i = 0 try: while True: v = self[i] yield v i += 1 except IndexError: return def __contains__(self, value): for v in self: if v is value or v == value: return True return False def __reversed__(self): for i in reversed(range(len(self))): yield self[i] def index(self, value, start=0, stop=None): '''S.index(value, [start, [stop]]) -> integer -- return first index of value. Raises ValueError if the value is not present. ''' if start is not None and start < 0: start = max(len(self) + start, 0) if stop is not None and stop < 0: stop += len(self) i = start while stop is None or i < stop: try: v = self[i] if v is value or v == value: return i except IndexError: break i += 1 raise ValueError def count(self, value): 'S.count(value) -> integer -- return number of occurrences of value' return sum(1 for v in self if v is value or v == value) Sequence.register(tuple) Sequence.register(str) Sequence.register(range) Sequence.register(memoryview) class ByteString(Sequence): """This unifies bytes and bytearray. XXX Should add all their methods. """ __slots__ = () ByteString.register(bytes) ByteString.register(bytearray) class MutableSequence(Sequence): __slots__ = () """All the operations on a read-write sequence. Concrete subclasses must provide __new__ or __init__, __getitem__, __setitem__, __delitem__, __len__, and insert(). """ @abstractmethod def __setitem__(self, index, value): raise IndexError @abstractmethod def __delitem__(self, index): raise IndexError @abstractmethod def insert(self, index, value): 'S.insert(index, value) -- insert value before index' raise IndexError def append(self, value): 'S.append(value) -- append value to the end of the sequence' self.insert(len(self), value) def clear(self): 'S.clear() -> None -- remove all items from S' try: while True: self.pop() except IndexError: pass def reverse(self): 'S.reverse() -- reverse *IN PLACE*' n = len(self) for i in range(n//2): self[i], self[n-i-1] = self[n-i-1], self[i] def extend(self, values): 'S.extend(iterable) -- extend sequence by appending elements from the iterable' for v in values: self.append(v) def pop(self, index=-1): '''S.pop([index]) -> item -- remove and return item at index (default last). Raise IndexError if list is empty or index is out of range. ''' v = self[index] del self[index] return v def remove(self, value): '''S.remove(value) -- remove first occurrence of value. Raise ValueError if the value is not present. ''' del self[self.index(value)] def __iadd__(self, values): self.extend(values) return self MutableSequence.register(list) MutableSequence.register(bytearray) # Multiply inheriting, see ByteString

1.3.使用isinstance而不是type
(1)語法:
isinstance(object, classinfo)
其中,object 是變量,classinfo 是類型即 (tuple,dict,int,float,list,bool等) 和 class類
若參數 object 是 classinfo 類的實例,或者 object 是 classinfo 類的子類的一個實例, 返回 True。
若 object 不是一個給定類型的的對象, 則返回結果總是False。
若 classinfo 不是一種數據類型或者由數據類型構成的元組,將引發一個 TypeError 異常。
(2)isinstance簡單用法
>>> isinstance(1,int) True >>> >>> isinstance('1',str) True >>> >>> isinstance(1,list) False
(3)type()與isinstance()的區別:
- 共同點:兩者都可以判斷對象類型
- 不同點:對於一個 class 類的子類對象類型判斷,type就不行了,而 isinstance 可以。
class A: pass class B(A): pass b = B() #判斷b是不是B的類型 print(isinstance(b,B)) #True # b是不是A的類型呢,也是的 #因為B繼承A,isinstance內部會去檢查繼承鏈 print(isinstance(b,A)) #True print(type(b) is B) #True #b指向了B()對象,雖然A是B的父類,但是A是另外一個對象,它們的id是不相等的 print(type(b) is A) #False
1.4.類變量和實例變量
python的類變量和實例變量,顧名思義,類變量是指跟類的變量,而實例變量,指跟類的具體實例相關聯的變量
class A: #類變量 bb = 11 def __init__(self,x,y): #實例變量 self.x = x self.y = y a = A(2,3) A.bb = 111111 print(a.x,a.y,a.bb) # 2 3 111111 print(A.bb) # 111111 a.bb = 2222 #實際上會在實例對象a里面新建一個屬性bb print(a.bb) # 2222 print(A.bb) # 111111
1.5.類和實例屬性的查找順序

class D: pass class C(D): pass class B(D): pass class A(B,C): pass #順序:A,B,C,D #__mro__,類的屬性查找順序 print(A.__mro__) #(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

class D: pass class E: pass class C(E): pass class B(D): pass class A(B,C): pass #順序:A,B,D,C,E #__mro__,類的屬性查找順序 print(A.__mro__) #(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
1.6.類方法,靜態方法,和實例方法
實例:
class Date(): #構造函數 def __init__(self,year,month,day): self.year = year self.month = month self.day = day #實例方法 def tomorrow(self): self.day += 1 # 靜態方法不用寫self @staticmethod def parse_from_string(date_str): year, month, day = tuple(date_str.split("-")) # 靜態方法不好的地方是采用硬編碼,如果用類方法的話就不會了 return Date(int(year), int(month), int(day)) #類方法 @classmethod def from_string(cls, date_str): year, month, day = tuple(date_str.split("-")) # cls:傳進來的類,而不是像靜態方法把類寫死了 return cls(int(year), int(month), int(day)) def __str__(self): return '%s/%s/%s'%(self.year,self.month,self.day) if __name__ == "__main__": new_day = Date(2018,5,9) #實例方法 new_day.tomorrow() print(new_day) #2018/5/10 #靜態方法 date_str = '2018-05-09' new_day = Date.parse_from_string(date_str) print(new_day) #2018/5/9 # 類方法 date_str = '2018-05-09' new_day = Date.from_string(date_str) print(new_day) # 2018/5/9
1.7.python對象的自省機制
在計算機編程中,自省是指一種能力:檢查某些事物以確定它是什么、它知道什么以及它能做什么。自省向程序員提供了極大的靈活性和控制力。
class Person: '''人類''' name = "user" class Student(Person): def __init__(self,school_name): self.school_name = school_name if __name__ == "__main__": user = Student('仙劍') #通過 __dict__ 查詢有哪些屬性 print(user.__dict__) #{'school_name': '仙劍'} print(Person.__dict__) #{'__module__': '__main__', '__doc__': '人類', 'name': 'user', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>} print(Person.__doc__) #人類 #可以添加屬性 user.__dict__['school_addr'] = '北京' print(user.school_addr) #北京 #dir也可以查看屬性,比__dict__功能更強大 print(dir(user)) #['__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__', 'name', 'school_addr', 'school_name']
1.8.super函數
super執行的順序
class A: def __init__(self): print('A') class B(A): def __init__(self): print('B') super().__init__() class C(A): def __init__(self): print('C') super().__init__() class D(B,C): def __init__(self): print('D') super(D, self).__init__() if __name__ == '__main__': print(D.__mro__) #(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) d = D() #執行結果 D B C A
1.9.with語句(上下文管理器)
#上下文管理器 class Sample: def __enter__(self): print('enter') #獲取資源 return self def __exit__(self, exc_type, exc_val, exc_tb): #釋放資源 print('exit') def do_something(self): print('doing something') #會自動執行enter和exit方法 with Sample() as sample: sample.do_something() # 運行結果 enter doing something exit
