1.魔法函數 python中常見的內置類型 什麼是魔法函數? python的魔法函數總被雙下劃線包圍,它們可以給你的類增加特殊的方法。如果你的對象實現了這些方法中的一個,那麼這個方法就會在特殊情況下被調用,你可以定義想要 的行為,而這一切都是自動發生的。 魔法函數一覽 魔法函數舉例 1.1.__ge ...
1.魔法函數
python中常見的內置類型
什麼是魔法函數?
python的魔法函數總被雙下劃線包圍,它們可以給你的類增加特殊的方法。如果你的對象實現了這些方法中的一個,那麼這個方法就會在特殊情況下被調用,你可以定義想要
的行為,而這一切都是自動發生的。
魔法函數一覽
魔法函數舉例
1.1.__getitem__
把對象變成可迭代的對象
例子:
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'])
#加了魔法函數“__getitem__”,類就成了可迭代的了
for em in company:
print(em) #11,22,33
如果不用魔法函數迴圈出每個員工的方法
class Company(object):
def __init__(self,employee_list):
self.employee = employee_list
company = Company(['11','22','33'])
for em in company.employee:
print(em)
還可以切片和獲取長度
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'])
#可以切片
company1 = company[:2]
#可以判斷len長度
print(len(company1)) #2
for em in company1:
print(em) #11,22
1.2.__len__
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
#
# def __getitem__(self, item):
# return self.employee[item]
def __len__(self):
return len(self.employee)
company = Company(["11", "22", "33"])
#如果不加魔法函數,len(company)會報錯的
print(len(company)) #3
1.3. __repr__
和__str__
1.安裝交互環境(jupyter)
pip install -i https://pypi.douban.com/simple ipython
pip install -i https://pypi.douban.com/simple notebook
#啟動
ipython notebook
2.__repr__
和__str__
的用法
2.深入類和對象
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
3.python元類編程
1.1.propety動態屬性
在面向對象編程中,我們一般把名詞性的東西映射成屬性,動詞性的東西映射成方法。在python中他們對應的分別是屬性self.xxx
和類方法。但有時我們需要的屬性需要根據其他屬性動態的計算,此時如果直接使用屬性方法處理,會導致數據不同步。下麵介紹@property
方法來動態創建類屬性。
from datetime import datetime,date
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
self._age = 0
@property
def age(self):
return datetime.now().year - self.birthday.year
@age.setter
def age(self,value):
self._age = value
if __name__ == '__main__':
user = User("derek",date(year=1994,month=11,day=11))
user.age = 23
print(user._age) # 23
print(user.age) # 24 ,動態計算出來的
1.2.__getattr__和__getattribute__的區別
object.__getattr__(self, name)
找不到attribute的時候,會調用getattr,返回一個值或AttributeError異常。
object.__getattribute__(self, name)
無條件被調用,通過實例訪問屬性。如果class中定義了__getattr__()
,則__getattr__()
不會被調用(除非顯示調用或引發AttributeError異常)
(1)調用一個不存在的屬性
class User:
def __init__(self,info={}):
self.info = info
# def __getattr__(self, item):
# return self.info[item]
if __name__ == '__main__':
user = User(info={"name":"derek","age":24})
print(user.name)
會報錯
(2)加了__getattr__
之後就可以調用了
class User:
def __init__(self,info={}):
self.info = info
#__getattr__是在查找不到屬性的時候調用
def __getattr__(self, item):
return self.info[item]
if __name__ == '__main__':
user = User(info={"name":"derek","age":24})
print(user.name) #derek
(3)__getattribute__
class User:
def __init__(self,info={}):
self.info = info
#__getattr__是在查找不到屬性的時候調用
def __getattr__(self, item):
return self.info[item]
#__getattribute不管屬性存不存在,都訪問這個
def __getattribute__(self, item):
return "zhang_derek"
if __name__ == '__main__':
user = User(info={"name":"derek","age":24})
#不管屬性存不存在,都走__getattribute__
print(user.name) #zhang_derek #即使屬性存在也走__getattribute__
print(user.test) #zhang_derek #不存在的屬性也能列印
print(user.company) #zhang_derek #不存在的屬性也能列印
1.3.屬性描述符
驗證賦值的時候是不是int類型
#屬性描述符
import numbers
#只要一個類實現了下麵三種魔法函數中的一種,這個類就是屬性描述符
class IntField:
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
if not isinstance(value,numbers.Integral):
raise ValueError("必須為int")
self.value = value
def __delete__(self, instance):
pass
class User:
age = IntField()
if __name__ == '__main__':
user = User()
user.age = 24
print(user.age)
如果user.age=24,值是int,可以正常列印
如果user.age='test',傳一個字元串,則會報錯
1.4.__new__
和__init__
的區別
(1)__new__
方法如果不返回對象,不會執行init方法
class User:
def __new__(cls, *args, **kwargs):
print("in new")
def __init__(self,name):
print("in init")
self.name = name
# new是用用來控制對象的生成過程,在對象生成之前
# init是用來完善對象的
# 如果new方法不返回對象,則不會調用init函數
if __name__ == '__main__':
user = User("derek")
運行結果:沒有調用init方法
(2)返回對象就會執行init方法
class User:
def __new__(cls, *args, **kwargs):
print("in new") #in new
print(cls) #cls是當前class對象 <class '__main__.User'>
print(type(cls)) #<class 'type'>
return super().__new__(cls) #必須返回class對象,才會調用__init__方法
def __init__(self,name):
print("in init") #in init
print(self) #self是class的實例對象 <__main__.User object at 0x00000000021B8780>
print(type(self)) #<class '__main__.User'>
self.name = name
# new是用用來控制對象的生成過程,在對象生成之前
# init是用來完善對象的
# 如果new方法不返回對象,則不會調用init函數
if __name__ == '__main__':
user = User(name="derek")
#總結
# __new__ 用來創建實例,在返回的實例上執行__init__,如果不返回實例那麼__init__將不會執行
# __init__ 用來初始化實例,設置屬性什麼的
1.5.自定義元類
(1)前戲:通過傳入不同的字元串動態的創建不同的類
def create_class(name):
if name == 'user':
class User:
def __str__(self):
return "user"
return User
elif name == "company":
class Company:
def __str__(self):
return "company"
return Company
if __name__ == '__main__':
Myclass = create_class("user")
my_obj = Myclass()
print(my_obj) #user
print(type(my_obj)) #<class '__main__.create_class.<locals>.User'>
(2)用type創建
雖然上面的方法能夠創建,但很麻煩,下麵是type創建類的一個簡單實例
# 一個簡單type創建類的例子
#type(object_or_name, bases, dict)
#type裡面有三個參數,第一個類名,第二個基類名,第三個是屬性
User = type("User",(),{"name":"derek"})
my_obj = User()
print(my_obj.name) #derek
(3)不但可以定義屬性,還可以定義方法
def say(self): #必須加self
return "i am derek"
User = type("User",(),{"name":"derek","say":say})
my_obj = User()
print(my_obj.name) #derek
print(my_obj.say()) #i am derek
(4)讓type創建的類繼承一個基類
def say(self): #必須加self
return "i am derek"
class BaseClass:
def answer(self):
return "i am baseclass"
#type裡面有三個參數,第一個類名,第二個基類名,第三個是屬性
User = type("User",(BaseClass,),{"name":"derek","say":say})
if __name__ == '__main__':
my_obj = User()
print(my_obj.name) # derek
print(my_obj.say()) # i am derek
print(my_obj.answer()) # i am baseclass
1.6.什麼是元類?
元類就是創建類的類,比如上面的type
在實際編碼中,我們一般不直接用type去創建類,而是用元類的寫法,自定義一個元類metaclass去創建
# 把User類創建的過程委托給元類去做,這樣代碼的分離性比較好
class MetaClass(type):
def __new__(cls, *args, **kwargs):
return super().__new__(cls,*args, **kwargs)
class User(metaclass=MetaClass):
def __init__(self,name):
self.name = name
def __str__(self):
return "test"
if __name__ == '__main__':
#python中類的實例化過程,會首先尋找metaclass,通過metaclass去創建User類
my_obj = User(name="derek")
print(my_obj) #test
4.自定義序列類
1.1.序列類型的分類
1.2.序列的+和+=,extend和append的區別
from collections import abc
a = [1,2,]
c = a + [3,4]
print(c) #[1, 2, 3, 4]
#如果 + 元祖則會報錯, not tuple
# c = a + (3,4) #TypeError: can only concatenate list (not "tuple") to list
# + 是新生產一個list, += 是就地加,不會新生成list
#用+= 則可以是元祖,後面只要是可迭代的就行
#其原理是python內部抽象基類MutableSequence裡面有個魔法函數__iadd__來實現的
a += (3,4) #[1, 2, 3, 4]
print(a)
a.extend((5,6))
print(a) #[1, 2, 3, 4, 5, 6]
a.append((7,8))
print(a) #[1, 2, 3, 4, 5, 6, (7, 8)]
#可以看到extend和append結果並不一樣,append是把裡面當一個值傳進去,extend是迭代的傳進去
1.3.實現可切片的對象
(1)切片的用法
#模式[start:end:step]
"""
其中,第一個數字start表示切片開始位置,預設為0;
第二個數字end表示切片截止(但不包含)位置(預設為列表長度);
第三個數字step表示切片的步長(預設為1)。
當start為0時可以省略,當end為列表長度時可以省略,
當step為1時可以省略,並且省略步長時可以同時省略最後一個冒號。
另外,當step為負整數時,表示反向切片,這時start應該比end的值要大才行。
"""
aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
#切片返回的是一個新元素,不會改變原有的list
print (aList[::]) # 返回包含原列表中所有元素的新列表 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
print (aList[::-1]) # 返回包含原列表中所有元素的逆序列表 [17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
print (aList[::2]) # 隔一個取一個,獲取偶數位置的元素 [3, 5, 7, 11, 15]
print (aList[1::2]) # 隔一個取一個,獲取奇數位置的元素 [4, 6, 9, 13, 17]
print (aList[3:6]) # 指定切片的開始和結束位置 [6, 7, 9]
print(aList[0:100]) # 切片結束位置大於列表長度時,從列表尾部截斷 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
print(aList[100:]) # 切片開始位置大於列表長度時,返回空列表 []
# aList[len(aList):] = [9] # 在列表尾部增加元素
# aList[:0] = [1, 2] # 在列表頭部插入元素
# aList[3:3] = [4] # 在列表中間位置插入元素
# aList[:3] = [1, 2] # 替換列表元素,等號兩邊的列表長度相等
# aList[3:] = [4, 5, 6] # 等號兩邊的列表長度也可以不相等
# aList[::2] = [0] * 3 # 隔一個修改一個
# print (aList)
# aList[::2] = ['a', 'b', 'c'] # 隔一個修改一個
# aList[::2] = [1,2] # 左側切片不連續,等號兩邊列表長度必須相等 #會報錯
# aList[:3] = [] # 刪除列表中前3個元素
#刪除
# del aList[:3] # 切片元素連續
# del aList[::2] # 切片元素不連續,隔一個刪一個
(2)實現對象支持切片操作
from collections import abc
#Sequence協議
import numbers
class Group:
#支持切片操作
def __init__(self, group_name, company_name, staffs):
self.group_name = group_name
self.company_name = company_name
self.staffs = staffs
def __reversed__(self):
self.staffs.reverse()
def __getitem__(self, item):
#當前的類
cls = type(self)
#判斷類是不是可切片的對象
if isinstance(item, slice):
return cls(group_name=self.group_name, company_name=self.company_name, staffs=self.staffs[item])
elif isinstance(item, numbers.Integral):
return cls(group_name=self.group_name, company_name=self.company_name, staffs=[self.staffs[item]])
def __len__(self):
return len(self.staffs)
def __iter__(self):
return iter(self.staffs)
def __contains__(self, item):
if item in self.staffs:
return True
else:
return False
staffs = ["derek1", "derek2", "derek3", "derek4"]
group = Group(company_name="alibaba", group_name="user", staffs=staffs)
#現在對象就成可切片的對象了
#__getitem__
for user in group:
print(user)
#運行結果
# derek1
# derek2
# derek3
# derek4
#__contains__
if 'derek1' in group:
print('yes')
1.4.列表生成式,字典推導式
# odd_list = []
# for i in range(21):
# if i%2 == 1:
# odd_list.append(i)
# print(odd_list) #[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
#列表生成式
#1.取出1-20之間的基數
odd_list = [i for i in range(21) if i %2 == 1]
print(odd_list) #[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
#2.取出1-20之間的基數的平方
def hadle_item(item):
return item * item
odd_list = [hadle_item(i) for i in range(21) if i %2 == 1]
print(odd_list) #[1, 9, 25, 49, 81, 121, 169, 225, 289, 361]
利用字典推導式把字典的key和value做轉換:{key:value}變成{value:key}的形式
# 字典推導式的用法
my_dict = {'derek1':11,'derek2':22,'derek3':33}
reversed_dict = {value:key for key,value in my_dict.items()}
print(reversed_dict) #{11: 'derek1', 22: 'derek2', 33: 'derek3'}
https://www.cnblogs.com/derek1184405959/p/8579428.html