1.先に述べました
「抽象ベースクラスは、」言葉「は、基本クラスは」「親」、「アブストラクト」は、「偽」の手段であることがより「深い」を聞くかもしれないです
「抽象ベースクラスは」「偽の親」です。
元のクラスの前にサプリメント2
人民元は、文法クラスでクラスインスタンス化される前に言いました
变量名 = type("类名", ("继承的类",), {"属性名":"属性值"})
今、別の方法を紹介
class 类名(metaclass=元类名):
...
例えば:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# __author__: kainhuck
# 定义一个元类
class MyMetaClass(type):
def __new__(cls, name, bases, attrs):
'''
:param name: 类名
:param bases: 继承的基类
:param attrs: 拥有的属性
要求必须含有name属性
'''
name = attrs.get("name", None)
if name and not callable(name):
return type.__new__(cls, name, bases, attrs)
raise NotImplementedError("必须含有name属性")
# 定义普通类
# class MyClassA(metaclass=MyMetaClass): # 报错,没有定义name属性
# pass
# 定义普通类
# class MyClassB(metaclass=MyMetaClass): # 报错,没有定义name属性
# def name(self):
# pass
#
# class MyClassC(metaclass=MyMetaClass): # 报错,没有定义name属性
# def __init__(self):
# self.name = "kainhuck"
#
class MyClassD(metaclass=MyMetaClass): # 没有报错
name = "kainhuck"
3.アヒルタイプ
アヒルは、入力します。事がアヒルのように見え、アヒルのように鳴くならば、それはおそらくアヒルです。
Pythonでは、私たちは(例えば:アヒルコール)、特定の機能を持っている必要があります回があるオブジェクトは、その後、我々は、オブジェクトが検出するために、アヒルは我々のニーズを満たしていないかを決定することができます。しかし、このことについて、いくつかの欠点を考えて、私たちは本当に必要があるためであることは鸭子叫
、この方法、それは限り、彼はすべての権利であることをアヒルのように呼ばれることになるとアヒルではないかオブジェクト。
言葉は周りの一部であってもよく、私はあなたに例を挙げてみましょう
そのような機能があります:
def func(something):
print(something[0])
我々は機能を変更するために何かをする必要があります改善するためのコードを作成するためのパラメータのサポート添字インデックス - この関数は、引数の最初の要素を出力します、実際には、この条件を意味します。
オプション1。
def func(something):
if isinstance(something, (list, tuple, set)): # 这些方法支持下标索引
print(something[0])
else:
print("Error")
オプション1つの欠点:
定義何かを入力し、デフォルトに書く、貧しい開発
私たちは、限り実装するカスタムクラスなどのことを知っている
__getitem__
方法を添字インデックスをサポートするために使用することができます。
オプションII。
def func(something):
if hasattr(something, '__getitem__'):
print(something[0])
else:
print("Error")
オプション2つの欠点:
すべてではないが実現する
__getitem__
など、方法は下付きインデックスをサポートすることができます字典
タイプ
このように実際には...何の解決策もないようですが、この問題への完璧なソリューションの抽象基底クラス
4.抽象基底クラス
1.抽象基底クラスの定義は:
メタクラスによって実装Abc.ABCMetaのような、クラス抽象基底クラスであります
class AbstractClass(metaclass=abc.ABCMeta):
pass
2. registerメソッド
抽象基底クラスで定義されたことはregister
方法他のスーパークラスであることができます
例えば:
import abc
# 定义一个抽象基类
class AbstractClass(metaclass=abc.ABCMeta):
pass
# 定义一个普通类继承自object
class MyClass(object):
pass
# 把我们定义的抽象基类注册为MyClass的父类
AbstractClass.register(MyClass)
mc = MyClass()
print(issubclass(MyClass, AbstractClass)) # 输出True
print(isinstance(mc, AbstractClass)) # 输出True
# 将我们定义的抽象基类注册到系统定义的类
AbstractClass.register(list)
print(isinstance([], AbstractClass)) # 输出True
ポイント:抽象基底クラスが親クラスの別のクラスが、他のクラスになることができますがの抽象基底クラスのメソッドとプロパティを継承しません
前の実施例3に実装3.スキーム
オプション3。
from abc import ABCMeta
class MySequence(metaclass=ABCMeta):
pass
MySequence.register(list) # 注册为列表的父类
MySequence.register(tuple) # 注册为元组的父类
'''
也可以自定义一个类,将MySequence注册为其父类
'''
def func(something):
if isinstance(something, AbstractClass): # AbstractClass的子类
print(something[0])
else:
print("Error")
4. __subclasshook__
マジックメソッド
上記の例を読んで、あなたは間違いなく、抽象基底クラス上のたくさんの悩みを登録し、各クラスのために、イエスのPython開発者があまりにもそう思う、そう、と感じるでしょう__subclasshook__
。この方法では、登場しました
いくつかの説明:
- このメソッドは、抽象基底クラスで定義されています
- メソッドは、クラスメソッドとして定義する必要があります
- この方法では、3つの戻り値を持っています
- 真:テストはクラスのサブクラスであるとみなされた場合
- 偽:テストクラスをサブクラスと見なされていない場合
- NotImplemented:後ろの話
抽象ベースクラスの定義:
import abc
class AbstractDuck(metaclass=abc.ABCMeta):
@classmethod
def __subclasshook__(cls, subclass):
quack = getattr(subclass, 'quack', None) # 取出subclass的 quack 属性,如果不存在则返回 None
return callable(quack) # 返回quack是否可以调用(是否是个方法)
2つのテストクラスを定義
class Duck(object):
def quack(self):
pass
class NotDuck(object):
quack = "foo"
サブクラスかどうかを決定しAbstractDuck
print(issubclass(Duck, AbstractDuck)) # 输出 True
print(issubclass(NotDuck, AbstractDuck)) # 输出 False
注:__subclasshook__
より優先順位の高い方法register
例えば、説明NotImplemented
戻り値を
In [6]: import abc
In [7]: class AbstractDuck(metaclass=abc.ABCMeta):
...: @classmethod
...: def __subclasshook__(cls, subclass):
...: quack = getattr(subclass, 'quack', None) # 取出subclass的 quack 属性,如果不存在则返回 None
...: if callable(quack):
...: return True
...: return NotImplemented
...:
In [8]: class Duck(object):
...: def quack(self):
...: pass
...:
In [9]: class NotDuck(object):
...: quack = "foo"
...:
In [10]: issubclass(NotDuck, AbstractDuck)
Out[10]: False
In [11]: AbstractDuck.register(NotDuck)
Out[11]: __main__.NotDuck
In [12]: issubclass(NotDuck, AbstractDuck)
Out[12]: True