OPからの複数のコメントの後、回答を最初から書き直すことにしました。
考えられる回避策:
class MyUnicodeMetaClass(type):
autocast_methods = ('__add__', '__radd__', 'format')
def __init__(cls, name, bases, attrs):
super(MyUnicodeMetaClass, cls).__init__(name, bases, attrs)
for method_name in MyUnicodeMetaClass.autocast_methods:
try:
setattr(cls, method_name, cls.autocast_creator(method_name))
except AttributeError:
if method_name.startswith('__r'):
setattr(cls, method_name, cls.autocast_reverse(method_name))
else:
raise
def autocast_creator(cls, method_name):
method = unicode().__getattribute__(method_name)
def autocast_method(self, *args, **kwargs):
method = unicode(self).__getattribute__(method_name)
return cls(method(*args, **kwargs))
return autocast_method
def autocast_reverse(cls, method_name):
method_name = method_name.replace('__r', '__', 1)
def autocast_method(self, *args, **kwargs):
method = unicode(args[0]).__getattribute__(method_name)
return cls(method(self, *args[1:], **kwargs))
return autocast_method
class MyUnicode(unicode):
__metaclass__ = MyUnicodeMetaClass
a = MyUnicode(u'aaa {0}')
print a, type(a)
# aaa {0} <class '__main__.MyUnicode'>
b = a + u'bbb'
print b, type(b)
# aaa {0}bbb <class '__main__.MyUnicode'>
c = u'ddd' + a
print c, type(c)
# cccaaa {0} <class '__main__.MyUnicode'>
d = a.format(115)
print d, type(d)
# aaa 115 <class '__main__.MyUnicode'>
拡張が必要になる場合がありますが、ベース スケルトンは準備ができています。
ここで何が起きてるの?
1.クラスMetaclass
の作成を変更するために使用されます。
2. Simpleは、 の代わりに返されるメソッドをクラスに入力するために使用されます。
3.リバース メソッドを提供するために、もう少し洗練された方法が使用されます(最初のオペランドがで、2 番目のオペランドが である場合に必要になるなど) 。MyUnicode
autocast_creator
MyUnicode
MyUnicode
unicode
autocast_reverse
__radd__
unicode
MyUnicode
autocast_methods
背景情報:
継承:
オブジェクト指向プログラミングは、実際の言葉を可能な限り反映することを目的としています。
ここでは継承も例外ではありません。
現実の世界では、ゾウの群れは常に動物の群れです。ここで間違いありません。
しかし、動物のグループはゾウのグループかもしれませんが、さまざまな動物のグループである可能性もあり、このグループにゾウがいないことさえあります.
これは、象のどのグループも特別な種類の動物のグループであるためです。のサブクラスとして
定義することで、コンピュータプログラムに反映させることができます。
どのように拡張できますか? たとえば、 new fieldと new methodを定義します。
このような単純な操作を考えてみましょう。
期待される結果のクラスは何ですか?ElephantGroup
AnimalGroup
ElephantGroup
AnimalGroup
ivory_weight
toot()
ElephantGroup() + AnimalGroup()
AnimalGroup
-ここには魔法がなく、ネズミ、イルカなどは象になりません。ネズミとイルカは象牙を提供せず、歯を出すこともできません。
MyUnicode
とに戻りましょうunicode
。
マトリックスやターミネーターで提示された意味では、機械は知的ではありません。
Python インタープリターは、 の目的を理解していませんMyUnicode
。名前が付けられ、電子メール アドレスを保持することを目的としたor (ここではあまり重要ではありません) を
拡張するクラスを考えてみましょう。当然のことです:)
そして、コード スニペットができました。unicode
str
EmailAddress
a = EmailAddress(u'example@example.com')
b = u'/!\n'
c = a + b
d = b + a
まだ?のインスタンスになることを期待c
しています。(または?)はいと答え
た場合は、次のことを教えてください
。そうでない場合は例外が発生します... 2. インタープリターは、実行せずに任意のインスタンスでインスタンスを
安全に初期化できることをどのように認識できますか? また、これは Python であり、実行時に動的に変更することもできることを覚えておいてください。覚えておいてください - インスタンスをその先祖のいずれかにいつでもキャストできます。逆の操作は暗黙的に行うことはできません。インタプリタが暗黙的にインスタンスをd
EmailAddress
MyUnicode
EmailAddress.__init__(...)
MyUnicode
unicode
__init__
__init__
object
objects
サブクラス。
このstrip()
メソッドは同じ規則に従います。unicode
文字はオリジナルから削除され、新しいunicode
インスタンスへの参照が返されます (まったく同じものunicode
が存在しない場合 - この場合、既存のインスタンスへの参照が返されます)。
インスタンスクラスの参照:
あなたのコメントの1つでcls
、実行チェーンを開始したインスタンスのクラスを参照していると述べました...は、インスタンスを持たないことを示すために、およびメソッド
cls
で使用される命名規則です-クラスしかありません。
実際、これらのケースのいずれにおいてもインスタンスにアクセスすることはできませんが、ほとんどの場合、新しいインスタンスを返す必要があります。 metaclasses
classmethods
__new__()
__new__()
identifier.__class__
属性を考えていたのでしょう。実行チェーンとも関係ありません。によって参照されるインスタンスの実際のクラスを指しますidentifier
。サブクラスを作成するためにおよび
のメソッドを使用することを期待するのはなぜですか?
サブクラスに何かを暗黙的にキャストすることは、予期される動作ではありません。あなたのコードのオペランドの 1 つはですが、もう 1 つはそうです。unicode
str
MyUnicode
unicode
strip()
unicode
Unicode 実装の詳細:
Pythonunicode
とstring
型は不変でユニークです(説明は後ほど)。不変とは、それらに対する変更操作がそれぞれまたはの他のインスタンスを返すことを意味します。他のインスタンスは新しいインスタンスを意味しますが、私が言ったように、これらのタイプは一意です。
その意味?コードを参照してください:unicode
string
a = u'aaa'
b = u'aaa'
ここで何が起こったのですか?初期化するために作成され
た の新しいインスタンスがありました。
初期化するオブジェクトが見つかったため、新しいインスタンスは作成されませんでした。
代わりに、オブジェクト保持への参照カウンターがインクリメントされました。 unicode
a
unicode
b
unicode
u'aaa'
それがわかったら、次のコードを検討してください。
a = u'aaa'
b = MyUnicode(u'aa')
c = b + u'a'
変数には正確に何が格納されc
ますか? オブジェクトへの参照unicode
- によって参照される同じオブジェクトa
。
変更してc
も影響がないのはなぜa
ですか? unicode
は不変であり、基になるオブジェクトは変更されないためです。
次の行が の場合、c = c + u'b'
new c
/other インスタンスへの参照が取得され、参照されるオブジェクトa
の参照カウンタが減少します。
結論:
Pythonunicode
とstr
クラスは一貫性があり、予測的です。
最適化、特別な目的、または実装の詳細のために、派生するのが難しい型がいくつかあります。サブクラス化することは意図されていませんが、たとえば私のスニペットのように実現でき
unicode
ます。 str
metaclass
いつものように、建設的な批判やコメントをお待ちしています。
幸運を!