Python類の高度な使い方
21587 ワード
カスタムクラス
__ iter__
クラスがfor...inループに使用されたい場合、listまたはtupleのように、
__ getitem__
Fibインスタンスはforループに作用してlistに似ているように見えるが、listとして使用するのはやはりだめであり、リストのように下付きで要素を取り出すことはできず、listのように下付きで要素を取り出すように表現するには
次のいずれかの項目にアクセスできます.
列挙クラス
定数を定義する必要がある場合は、月などの大文字変数を整数で定義します.
利点は簡単で、欠点はタイプがintであり、変数であることです.より良い方法は、このような列挙タイプのclassタイプを定義し、各定数がclassの唯一のインスタンスであることです.Enumによって実現できます.
すべてのメンバーを列挙します.
valueの値のデフォルトは1からです.列挙タイプをカスタマイズするには、Enumからカスタムクラスを派生できます.
メンバー名で列挙定数を参照するか、valueの値に基づいて列挙定数を直接取得できます.
メタクラスの使用
type()
動的言語と静的言語の最大の違いは、コンパイル時に定義されるのではなく、実行時に動的に作成される関数とクラスの定義です.classの定義は実行時に動的に作成され、classを作成する方法は
classオブジェクトを作成するには、type()関数から3つのパラメータが順次入力されます. classの名前. 継承の親クラスの集合は、Pythonが多重継承をサポートしていることに注意してください.親クラスが1つしかない場合は、tupleの単一要素の書き方を忘れないでください. classのメソッド名は関数にバインドされ、ここでは関数fnをメソッド名helloにバインドする.
metaclass
ListMetaclassがあれば、クラスを定義するときにListMetaclassを使用してクラスをカスタマイズするよう指示し、キーワードパラメータmetaclassを入力します.現在作成するクラスのオブジェクト. 類の名前. クラスが継承する親クラスの集合. クラスのメソッド集合.
__ iter__
クラスがfor...inループに使用されたい場合、listまたはtupleのように、
__iter__()
メソッドを実装する必要があります.このメソッドは反復オブジェクトを返し、Pythonのforループは反復オブジェクトの__next__()
メソッドを呼び出し続け、StopIteration
エラーが発生するまでループの次の値を取得します.たとえば、フィボナッチ数列を例にとると、forループに作用するFibクラスを書きます.class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > 10000:
raise StopIteration()
return self. a
for n in Fib():
print(n)
__ getitem__
Fibインスタンスはforループに作用してlistに似ているように見えるが、listとして使用するのはやはりだめであり、リストのように下付きで要素を取り出すことはできず、listのように下付きで要素を取り出すように表現するには
__getitem__()
の方法が必要である.class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
次のいずれかの項目にアクセスできます.
>>> f = Fib()
>>> f[0]
1
>>> f[1]
1
>>> f[2]
2
>>> f[3]
3
>>> f[10]
89
>>> f[100]
573147844013817084101
__getitem__()
メソッドはlistのスライス操作を実現することもできるが、判断を加える必要がある.class Fib(object):
def __getitem__(self, n):
if isinstance(n, int): # n
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice): # n
start = n.start
stop = n.stop
if start is None:
start = 0
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
>>> f = Fib()
>>> f[0:5]
[1, 1, 2, 3, 5]
>>> f[:10]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
列挙クラス
定数を定義する必要がある場合は、月などの大文字変数を整数で定義します.
JAN = 1
FEB = 2
MAR = 3
...
NOV = 11
DEC = 12
利点は簡単で、欠点はタイプがintであり、変数であることです.より良い方法は、このような列挙タイプのclassタイプを定義し、各定数がclassの唯一のインスタンスであることです.Enumによって実現できます.
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
すべてのメンバーを列挙します.
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
valueの値のデフォルトは1からです.列挙タイプをカスタマイズするには、Enumからカスタムクラスを派生できます.
from enum import Enum, unique
class Weekday(Enum):
Sun = 0 # Sun value 0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
メンバー名で列挙定数を参照するか、valueの値に基づいて列挙定数を直接取得できます.
メタクラスの使用
type()
動的言語と静的言語の最大の違いは、コンパイル時に定義されるのではなく、実行時に動的に作成される関数とクラスの定義です.classの定義は実行時に動的に作成され、classを作成する方法は
type()
関数を使用することです.たとえば、type()
の定義を必要とせずに、class Hello(object)...
の関数でHelloクラスを作成できます.>>> def fn(self, name='world'): #
... print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>
classオブジェクトを作成するには、type()関数から3つのパラメータが順次入力されます.
metaclass
type()
を使用してクラスを動的に作成するほか、クラスの作成動作を制御するにはmetaclassを使用します.metaclassは、メタクラスと直訳され、簡単な解釈では、クラスを定義した後、このクラスに基づいてインスタンスを作成することができるので、クラスを定義してからインスタンスを作成します.しかし、クラスを作成したい場合は?では、metaclassに基づいてクラスを作成する必要があります.そのため、metaclassを定義してからクラスを作成します.Metaclassを使用してMylistクラスにadd()
メソッドを追加します.# metaclass , `type` :
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
ListMetaclassがあれば、クラスを定義するときにListMetaclassを使用してクラスをカスタマイズするよう指示し、キーワードパラメータmetaclassを入力します.
class MyList(list, metaclass=ListMetaclass):
pass
__new__()
メソッドで受信されたパラメータは、次の順です.