「変数」はインスタンス変数である場合 - あなたが__init__
方法のチェーンの任意の時点であれば、そう:
def __init__(self):
self.findMe = "Here I am!"
それはその時点からインスタンス変数である、とすることはできませんため、すべてのエフェクトは、他のインスタンス変数とは区別されます。 (特別な__setattr__
メソッドを持つクラスのような仕組みを入れないと、属性の変更を追跡し、コードセットのどの部分を属性に設定し直すか - この回答の最後の例を参照)
また
class parent(object):
def __init__(self):
findMe = "Here I am!"
findMe
は、そのメソッドへのローカル変数として定義され、
__init__
が終了した後も、存在しない、あなたの例であることに注意。
今、あなたの変数は継承チェーン上のどこかにクラス属性として設定されている場合:
class parent(object):
findMe = False
class childone(parent):
...
findMe
はMRO(メソッドでは、各クラスの__dict__
をイントロスペクトによって定義されたクラスを見つけることが可能です解決順序)チェーン。もちろん、MROチェーン内のすべてのクラスをイントロスペクトすることなくこれを行う方法はありません。以下の例のように定義された属性を追跡する場合は例外ですが、MRO自体のイントロスペクションはPythonの:もう一度
def __init__(self):
super().__init__()
...
findme_definer = [cls for cls in self.__class__.__mro__ if "findMe" in cls.__dict__][0]
- 継承ツリー内のすべての定義された属性を追跡し、各属性が定義されている場所を取得するために辞書を使用することになり、あなたの継承チェーンにメタクラスを持つことも可能であろう。同じメタクラスはすべて__init__
(またはすべてのメソッド)を自動的に装飾し、上に挙げたようにインスタンス属性を作成時に追跡できるように特別な__setitem__
を設定することもできます。
これは実行することができますが、少し複雑で、維持するのが難しく、おそらくあなたの問題に間違ったアプローチをしているというシグナルです。
クラス属性だけを記録するメタクラスは単純に(Python3構文 - まだPython 2を使用している場合はクラス本体に__metaclass__
属性を定義する)ことができます。7):今すぐ
class MetaBase(type):
definitions = {}
def __init__(cls, name, bases, dct):
for attr in dct.keys():
cls.__class__.definitions[attr] = cls
class parent(metaclass=MetaBase):
findMe = 5
def __init__(self):
print(self.__class__.definitions["findMe"])
、人は働くことができ、各クラスの各メソッドを包む、currentclassの属性を定義しただけで「ライブ」追跡メカニズムスーパークラスのどの検索したい場合 - それは多くのトリッキーです。
私はこれを作ったことがありますが、これはあまり必要がない場合でも、クラスクラスのクラス属性をクラスdefinitions
とインスタンス_definitions
辞書に記録していますメソッドは、特定のインスタンス属性を最後に設定している可能性があります(これは純粋なPython3であり、Python2が使用する "unbound method"のためにPython2に移植するのは難しく、Python3では単純な関数)
from threading import current_thread
from functools import wraps
from types import MethodType
from collections import defaultdict
def method_decorator(func, cls):
@wraps(func)
def wrapper(self, *args, **kw):
self.__class__.__class__.current_running_class[current_thread()].append(cls)
result = MethodType(func, self)(*args, **kw)
self.__class__.__class__.current_running_class[current_thread()].pop()
return result
return wrapper
class MetaBase(type):
definitions = {}
current_running_class = defaultdict(list)
def __init__(cls, name, bases, dct):
for attrname, attr in dct.items():
cls.__class__.definitions[attr] = cls
if callable(attr) and attrname != "__setattr__":
setattr(cls, attrname, method_decorator(attr, cls))
class Base(object, metaclass=MetaBase):
def __setattr__(self, attr, value):
if not hasattr(self, "_definitions"):
super().__setattr__("_definitions", {})
self._definitions[attr] = self.__class__.current_running_class[current_thread()][-1]
return super().__setattr__(attr,value)
例上記のコードのクラス:
class Parent(Base):
def __init__(self):
super().__init__()
self.findMe = 10
class Child1(Parent):
def __init__(self):
super().__init__()
self.findMe1 = 20
class Child2(Parent):
def __init__(self):
super().__init__()
self.findMe2 = 30
class GrandChild(Child1, Child2):
def __init__(self):
super().__init__()
def findall(self):
for attr in "findMe findMe1 findMe2".split():
print("Attr '{}' defined in class '{}' ".format(attr, self._definitions[attr].__name__))
とコンソールに1は、この結果を取得します:
In [87]: g = GrandChild()
In [88]: g.findall()
Attr 'findMe' defined in class 'Parent'
Attr 'findMe1' defined in class 'Child1'
Attr 'findMe2' defined in class 'Child2'
を...そしてあなたは 'おそらくfunction'のいくつかの並べ替えを呼び出すと言うとき、あなたはその関数がいずれかの継承階層をナビゲートしたくありません、右? – Gerrat