プロパティをクラスに動的に追加する方法は?


215

目標は、db結果セットのように動作するモッククラスを作成することです。

したがって、たとえば、データベースクエリがdict式を使用して返された場合{'ab':100, 'cd':200}、次のようにしたいと思います。

>>> dummy.ab
100

最初私は多分この方法でそれができると思った:

ks = ['ab', 'cd']
vs = [12, 34]
class C(dict):
    def __init__(self, ks, vs):
        for i, k in enumerate(ks):
            self[k] = vs[i]
            setattr(self, k, property(lambda x: vs[i], self.fn_readyonly))

    def fn_readonly(self, v)
        raise "It is ready only"

if __name__ == "__main__":
    c = C(ks, vs)
    print c.ab

しかし、c.ab代わりにプロパティオブジェクトを返します。

setattrラインを置き換えることk = property(lambda x: vs[i])は全く役に立ちません。

では、実行時にインスタンスプロパティを作成する正しい方法は何でしょうか。

PS私は、方法はどのように__getattribute__使用されているのかを示しています。


2
コードにはいくつかのタイプミスがあります。fn_readonlyの定義にはa :__init__参照が必要self.fn_readyonlyです。
mhawke 2009

あなたが正しいです。実行時にプロパティを作成する理由を強調するために、土壇場でそのセッター関数を追加しました。
アンソニーコング

初期化時にプロパティを作成する際の主な問題は、ヘルパーをすぐに呼び出した場合や、問題が発生した場合に、ヘルパーが存在しているにもかかわらず存在しないというエラーが発生することでした。以下の私のソリューションでは、2つのクラスを作成します。1つはベース/ペアレント(回避策を見つけようとしている)と、ベース/ペアレントを拡張するメインオブジェクトです。次に、メインオブジェクトで、初期化せずに、プロパティやヘルパー関数などを作成するAccessorFuncクリエーターを呼び出します。
Acecool

つまり、クラスExampleBase:pass; クラスExample(ExampleBase):__x = Accessor(ExampleBase、 'x'、 'X'、123); --- Xを使用してプロパティを作成し、Xを使用して名前付き関数を作成するため、GetX、SetXなどを使用し、プロパティに.x、._ x、.__ xを使用します。したがって、.xは、データが通過するプロパティ自体です(self.x = 123による取得/設定、または出力へのself.x)。格納されたRAWデータにself._xを使用しました。これにより、格納されたデータに設定することなく、デフォルト値を割り当てることもできるため、簡単にアクセスできるようになりました。したがって、_xはNoneで、.xは123を返すことができます。.__xはアクセサにリンクされています
Acecool

以下は、動的プロパティと動的関数を作成する基本バージョンへのリンクです。ファイルには他のバージョンへのリンクがたくさんあります。1つは、関数を使用してヘルパーを作成するAccessorFuncシステムです(1つは関数用、1つはプロパティ用、2つは個別の要素として、そのため、そのファイル内の何でもコード短縮を使用しません)。他のファイルにはそれがあります:dropbox.com/s/phnnuavssmzeqrr/dynamic_properties_simple.py
dl=

回答:


333

私は年を取って賢くなり、何が起こっているのかを知った今、この答えを広げるべきだと思います。遅れることはない。

あなたはできるクラスを動的にプロパティを追加します。しかし、それが問題です。クラスに追加する必要があります。

>>> class Foo(object):
...     pass
... 
>>> foo = Foo()
>>> foo.a = 3
>>> Foo.b = property(lambda self: self.a + 1)
>>> foo.b
4

A propertyは、実際には記述子と呼ばれるものの単純な実装です。これは、指定されたクラスで、指定された属性のカスタム処理を提供するオブジェクトです。巨大なif木をから因数分解する方法のようなちょっと__getattribute__

私が尋ねるときはfoo.b、上記の例では、Pythonはことを見ているbクラスが実装で定義された記述プロトコルちょうどそれが持つオブジェクトの意味-which __get____set__または__delete__方法。記述子はその属性を処理する責任があると主張しているため、Pythonはを呼び出しFoo.b.__get__(foo, Foo)、戻り値は属性の値として返されます。以下の場合にはproperty、これらの各方法は、単に呼び出してfgetfsetまたはfdelあなたがに渡されたpropertyコンストラクタ。

記述子は、実際にはOO実装全体の配管を公開するPythonの方法です。実際、よりもさらに一般的なタイプの記述子がありますproperty

>>> class Foo(object):
...     def bar(self):
...         pass
... 
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x7f2a439d5dd0>>
>>> Foo().bar.__get__
<method-wrapper '__get__' of instancemethod object at 0x7f2a43a8a5a0>

控えめなメソッドは、もう1つの種類の記述子です。その__get__最初の引数として呼び出すインスタンス上の鋲。実際、これは次のことを行います。

def __get__(self, instance, owner):
    return functools.partial(self.function, instance)

とにかく、これが記述子がクラスでのみ機能する理由だと思います。そもそも記述子はクラスを強化するものを形式化したものです。これらは規則の例外です。クラスに記述子を割り当てることができ、クラス自体がtype!のインスタンスです。実際、Foo.bまだ読み込もうとするとproperty.__get__、クラス属性としてアクセスされたときに記述子が自分自身を返すのは、単に慣用的です。

ほぼすべてのPythonのOOシステムをPythonで表現できるのはかなりクールだと思います。:)

ああ、そしてあなたが興味を持っているなら、記述子についての長いブログ記事をしばらく前に書いた。


35
add_propertyメソッドを追加する必要はありません。setattr (Foo, 'name', property (func))
コートニーD

8
あなたの「しかし、それが問題です...」は、私に数時間の作業を節約しました。ありがとうございました。
Matt Howell、

2
単一のインスタンスでプロパティを定義する場合は、実行時にクラスを作成し、__class__を変更できます。
Wilfred Hughes

1
@ myproperty.setterはどうですか?動的に追加する方法は?
LRMAAX

初期化されたオブジェクトにプロパティを追加する必要はありません。そうすることはそれがインスタンスにのみ付着することを意味するかもしれませんが、私はそれを再確認する必要があります。私は動的プロパティがインスタンスのみである同様の問題に遭遇したことを知っています。また、静的セットアップとオブジェクトに対するものでしたので、将来の初期化でそれらが利用されます。私の投稿は下にあり、ヘルパー関数とすべてに簡単にアクセスする簡単な方法を作成します。プロパティの.x、ゲッター/セッターが使用する生データ(Noneの場合もあります)の._x、およびアクセサーオブジェクトの.__ x。
Acecool

57

目標は、db結果セットのように動作するモッククラスを作成することです。

だからあなたが欲しいのはa ['b']をabと綴ることができる辞書ですか?

簡単だ:

class atdict(dict):
    __getattr__= dict.__getitem__
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

1
より一般的な設定では、これは限られた目的に役立ちます。辞書にd = {'a1':{'b': 'c'}、 'a2':...}のようなマルチレベルの階層がある場合、d.a1またはd.a2を実行できますが、次のことができます ' t do d.a1.b
Shreyas

1
心に留めておくべき一つのことは、これは辞書のメソッドや属性と同じ名前を持つ属性の属性値を設定することができることであるが、同じように再び値を取得することはできませんd.items = 1d.items戻ります<built-in method items of atdict object at ...>。代わりにの代わりにd["items"]使用または使用できますが、これにより、dictのメソッドのほとんどを使用でき__getattribute__なくなり__getattr__ます。
Marcono1234 2017

ムンクライブラリを使用してください!(束の分岐)
ブライアンピーターソン

38

namedtuple事前にフィールドのリスト全体を知っているので、この問題をで簡単に解決できるようです。

from collections import namedtuple

Foo = namedtuple('Foo', ['bar', 'quux'])

foo = Foo(bar=13, quux=74)
print foo.bar, foo.quux

foo2 = Foo()  # error

独自のセッターを作成する必要がある場合は、クラスレベルでメタプログラミングを行う必要があります。property()インスタンスでは機能しません。


いい案。残念ながら、現時点ではpython 2.4を使用しています。
アンソニーコング


2
書いた人namedtupleは、忠実なオブジェクト指向の原則であることをスムーズかつエレガントにするための賞に値します。
Keith Pinson、2011

4
申し訳ありませんが、せいぜい、この回答は、すべてが事前にわかっている読み取り専用属性のみで構成されるクラスが必要であるという特別な場合にのみ適用できます。言い換えると、実行時にクラスに読み取り専用のプロパティだけでなく、一般的なプロパティを追加する方法に関する幅広い質問に対応しているとは思いません(他の「アドオン」の回答の現在のバージョンも同様です)著者が投稿)。
martineau 2013年

@martineau so ...より多くの引数をproperty()?どちらの回答にも、読み取り専用プロパティに固有のものはありません。
Eevee 2013年

32

そのためにプロパティを使用する必要はありません。オーバーライド__setattr__して、読み取り専用にします。

class C(object):
    def __init__(self, keys, values):
        for (key, value) in zip(keys, values):
            self.__dict__[key] = value

    def __setattr__(self, name, value):
        raise Exception("It is read only!")

多田。

>>> c = C('abc', [1,2,3])
>>> c.a
1
>>> c.b
2
>>> c.c
3
>>> c.d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'd'
>>> c.d = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __setattr__
Exception: It is read only!
>>> c.a = 'blah'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __setattr__
Exception: It is read only!

9

プロパティをPythonクラスに動的に追加する方法は?

プロパティを追加したいオブジェクトがあるとしましょう。通常、下流で使用されるコードで属性へのアクセスの管理を開始する必要があるときに、一貫したAPIを維持できるようにプロパティを使用します。次に、通常はオブジェクトが定義されているソースコードにそれらを追加しますが、そのアクセス権がないか、プログラムで関数を本当に動的に選択する必要があるとします。

クラスを作成する

ドキュメントにproperty基づく例を使用して、「非表示」属性を持つオブジェクトのクラスを作成し、そのインスタンスを作成してみましょう。

class C(object):
    '''basic class'''
    _x = None

o = C()

Pythonでは、物事を行うための1つの明白な方法があると期待しています。ただし、この場合は、デコレーター表記を使用する方法と使用しない方法の2つの方法を示します。まず、デコレータ表記なし。これは、getter、setter、またはdeleterを動的に割り当てる場合に役立ちます。

動的(別名モンキーパッチ)

クラスのいくつかを作成しましょう:

def getx(self):
    return self._x

def setx(self, value):
    self._x = value

def delx(self):
    del self._x

そして、これらをプロパティに割り当てます。ここで、動的な質問に答えて、プログラムで関数を選択できることに注意してください。

C.x = property(getx, setx, delx, "I'm the 'x' property.")

そして使い方:

>>> o.x = 'foo'
>>> o.x
'foo'
>>> del o.x
>>> print(o.x)
None
>>> help(C.x)
Help on property:

    I'm the 'x' property.

デコレータ

上記と同じように、デコレータ表記で同じことを行うことができますが、この場合、メソッドにはすべて同じ名前を付ける必要があります(したがって、属性と同じ名前にすることをお勧めします)。したがって、プログラムによる割り当てはそれほど簡単ではありません。上記の方法を使用しています:

@property
def x(self):
    '''I'm the 'x' property.'''
    return self._x

@x.setter
def x(self, value):
    self._x = value

@x.deleter
def x(self):
    del self._x

そして、プロパティオブジェクトとそのプロビジョニングされたセッターおよびデリーターをクラスに割り当てます。

C.x = x

そして使い方:

>>> help(C.x)
Help on property:

    I'm the 'x' property.

>>> o.x
>>> o.x = 'foo'
>>> o.x
'foo'
>>> del o.x
>>> print(o.x)
None

5

このStack Overflowの投稿で同様の質問して、単純な型を作成するクラスファクトリを作成しました。結果は、クラスファクトリの作業バージョンを持つこの回答でした。これが答えの抜粋です:

def Struct(*args, **kwargs):
    def init(self, *iargs, **ikwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)
        for i in range(len(iargs)):
            setattr(self, args[i], iargs[i])
        for k,v in ikwargs.items():
            setattr(self, k, v)

    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    return type(name, (object,), {'__init__': init, '__slots__': kwargs.keys()})

>>> Person = Struct('fname', 'age')
>>> person1 = Person('Kevin', 25)
>>> person2 = Person(age=42, fname='Terry')
>>> person1.age += 10
>>> person2.age -= 10
>>> person1.fname, person1.age, person2.fname, person2.age
('Kevin', 35, 'Terry', 32)
>>>

あなたはこれのいくつかのバリエーションを使用して、あなたの目標であるデフォルト値を作成することができます(これを扱う質問にも答えがあります)。


4

質問を完全に理解しているかどうかはわかりません__dict__が、クラスの組み込みを使用して、実行時にインスタンスプロパティを変更できます。

class C(object):
    def __init__(self, ks, vs):
        self.__dict__ = dict(zip(ks, vs))


if __name__ == "__main__":
    ks = ['ab', 'cd']
    vs = [12, 34]
    c = C(ks, vs)
    print(c.ab) # 12

基本的に、私の質問は、実行時に新しいプロパティを作成できるかどうかを調べることです。コンセンサスは否定的なようです。あなたの提案は確かにシンプルで実用的です。(dictを使用する他の回答と同じ)
Anthony Kong

簡単な答えはまた、次のようになりますself.__dict__[key] = value
アランKarlson

4

検索エンジンから来た人のために、動的プロパティについて話すときに私が探していた2つのことを以下に示します。

class Foo:
    def __init__(self):
        # we can dynamically have access to the properties dict using __dict__
        self.__dict__['foo'] = 'bar'

assert Foo().foo == 'bar'


# or we can use __getattr__ and __setattr__ to execute code on set/get
class Bar:
    def __init__(self):
        self._data = {}
    def __getattr__(self, key):
        return self._data[key]
    def __setattr__(self, key, value):
        self._data[key] = value

bar = Bar()
bar.foo = 'bar'
assert bar.foo == 'bar'

__dict__動的に作成されたプロパティを配置する場合に適しています。__getattr__データベースにクエリを実行するなど、値が必要な場合にのみ何かを行うのに適しています。set / getコンボは、クラスに格納されたデータへのアクセスを簡略化するのに適しています(上記の例のように)。

動的プロパティが1つだけ必要な場合は、property()組み込み関数を確認してください。


4

property()プロパティはデータ記述子であるため、実行時に新しいをインスタンスに追加することはできません。代わりに__getattribute__、インスタンスでデータ記述子を処理するために、新しいクラスまたはオーバーロードを動的に作成する必要があります。


これは間違っています。プロパティをクラスに追加して、メソッドからアクセスできます。
アーメド

2

達成する最良の方法は、を定義すること__slots__です。これにより、インスタンスに新しい属性を設定できなくなります。

ks = ['ab', 'cd']
vs = [12, 34]

class C(dict):
    __slots__ = []
    def __init__(self, ks, vs): self.update(zip(ks, vs))
    def __getattr__(self, key): return self[key]

if __name__ == "__main__":
    c = C(ks, vs)
    print c.ab

そのプリント 12

    c.ab = 33

それは与える: AttributeError: 'C' object has no attribute 'ab'


2

望ましい効果を達成する方法のもう1つの例

class Foo(object):

    _bar = None

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        self._bar = value

    def __init__(self, dyn_property_name):
        setattr(Foo, dyn_property_name, Foo.bar)

これで、次のようなことができるようになります。

>>> foo = Foo('baz')
>>> foo.baz = 5
>>> foo.bar
5
>>> foo.baz
5

2

以下がその解決策です。

  • プロパティ名を文字列として指定できるため、プログラムにすべてリストされるのではなく、外部のデータソースから取得することができます。
  • オブジェクトが作成されるたびではなく、クラスが定義されたときにプロパティを追加します

クラスが定義されたら、これを行ってプロパティを動的に追加します。

setattr(SomeClass, 'propertyName', property(getter, setter))

Python 3でテストした完全な例を次に示します。

#!/usr/bin/env python3

class Foo():
  pass

def get_x(self):
  return 3

def set_x(self, value):
  print("set x on %s to %d" % (self, value))

setattr(Foo, 'x', property(get_x, set_x))

foo1 = Foo()
foo1.x = 12
print(foo1.x)

1

次のコードを使用すると、辞書オブジェクトを使用してクラス属性を更新できます。

class ExampleClass():
    def __init__(self, argv):
        for key, val in argv.items():
            self.__dict__[key] = val

if __name__ == '__main__':
    argv = {'intro': 'Hello World!'}
    instance = ExampleClass(argv)
    print instance.intro

1

これはOPが望んだものとは少し異なりますが、実用的な解決策が見つかるまで脳をガタガタ動かしたので、次の男/ギャルのためにここに入れます

動的セッターとゲッターを指定する方法が必要でした。

class X:
    def __init__(self, a=0, b=0, c=0):
        self.a = a
        self.b = b
        self.c = c

    @classmethod
    def _make_properties(cls, field_name, inc):
        _inc = inc

        def _get_properties(self):
            if not hasattr(self, '_%s_inc' % field_name):
                setattr(self, '_%s_inc' % field_name, _inc)
                inc = _inc
            else:
                inc = getattr(self, '_%s_inc' % field_name)

            return getattr(self, field_name) + inc

        def _set_properties(self, value):
            setattr(self, '_%s_inc' % field_name, value)

        return property(_get_properties, _set_properties)

私は自分のフィールドを事前に知っているので、自分のプロパティを作成します。注:このPERインスタンスは実行できません。これらのプロパティはクラスに存在します!!!

for inc, field in enumerate(['a', 'b', 'c']):
    setattr(X, '%s_summed' % field, X._make_properties(field, inc))

それをすべてテストしてみましょう。

x = X()
assert x.a == 0
assert x.b == 0
assert x.c == 0

assert x.a_summed == 0  # enumerate() set inc to 0 + 0 = 0
assert x.b_summed == 1  # enumerate() set inc to 1 + 0 = 1
assert x.c_summed == 2  # enumerate() set inc to 2 + 0 = 2

# we set the variables to something
x.a = 1
x.b = 2
x.c = 3

assert x.a_summed == 1  # enumerate() set inc to 0 + 1 = 1
assert x.b_summed == 3  # enumerate() set inc to 1 + 2 = 3
assert x.c_summed == 5  # enumerate() set inc to 2 + 3 = 5

# we're changing the inc now
x.a_summed = 1 
x.b_summed = 3 
x.c_summed = 5

assert x.a_summed == 2  # we set inc to 1 + the property was 1 = 2
assert x.b_summed == 5  # we set inc to 3 + the property was 2 = 5
assert x.c_summed == 8  # we set inc to 5 + the property was 3 = 8

混乱していますか?はい、申し訳ありませんが、意味のある実世界の例を思い付くことができませんでした。また、これは心の軽い人のためのものではありません。


私が正しく思い出せば、すべてのテスト中に静的タイプのプロパティ/動的に追加されたg / setterを作成する方法を見つけました。以前のすべてを実行する必要がありますが、すべてのインスタンス間で共有される何かを追加できることは間違いなく可能です。インスタンスごとのプロセスで作成する場合については、あるインスタンスに別のインスタンスが作成しないようにできると確信しています。私は検証する必要がありますが、私もこのようなものに遭遇しました(最初の試行で、関数を作成する原因となった間違いを犯しましたが、欠陥のためにすべてのインスタンスにそれらがあったわけではありません)
Acecool

また、これは知識のリポジトリであるため、考えられるあらゆる解決策を歓迎します。さまざまな人々が問題の解決策を作成するさまざまな方法を見るのもまたワクワクします。私の解決策はLOTを実行します、あなたはこれを共有するのがより簡単なものに削りました。私も私の小さな変形をしました-それはこのトピックのどこかにあるはずです-そして私はそれが私が投稿したものではないことに気づきました:-)...
Acecool

0

これはうまくいくようです(しかし以下を参照してください):

class data(dict,object):
    def __init__(self,*args,**argd):
        dict.__init__(self,*args,**argd)
        self.__dict__.update(self)
    def __setattr__(self,name,value):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
    def __delattr__(self,name):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)

より複雑な動作が必要な場合は、回答を自由に編集してください。

編集する

大規模なデータセットの場合、おそらく次の方がメモリ効率が高くなります。

class data(dict,object):
    def __init__(self,*args,**argd):
        dict.__init__(self,*args,**argd)
    def __getattr__(self,name):
        return self[name]
    def __setattr__(self,name,value):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
    def __delattr__(self,name):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)

0

質問の主な目的に答えるために、不変のデータソースとしてdictからの読み取り専用属性が必要です。

目標は、db結果セットのように動作するモッククラスを作成することです。

したがって、たとえば、データベースクエリがdict式を使用して返された場合 {'ab':100, 'cd':200}、次のようになります。

>>> dummy.ab
100

これを実現namedtupleするためにcollectionsモジュールのaを使用する方法を示します。

import collections

data = {'ab':100, 'cd':200}

def maketuple(d):
    '''given a dict, return a namedtuple'''
    Tup = collections.namedtuple('TupName', d.keys()) # iterkeys in Python2
    return Tup(**d)

dummy = maketuple(data)
dummy.ab

戻り値 100


0
class atdict(dict):
  def __init__(self, value, **kwargs):
    super().__init__(**kwargs)
    self.__dict = value

  def __getattr__(self, name):
    for key in self.__dict:
      if type(self.__dict[key]) is list:
        for idx, item in enumerate(self.__dict[key]):
          if type(item) is dict:
            self.__dict[key][idx] = atdict(item)
      if type(self.__dict[key]) is dict:
        self.__dict[key] = atdict(self.__dict[key])
    return self.__dict[name]



d1 = atdict({'a' : {'b': [{'c': 1}, 2]}})

print(d1.a.b[0].c)

そして出力は:

>> 1

0

kjfletchからアイデアを拡張する

# This is my humble contribution, extending the idea to serialize
# data from and to tuples, comparison operations and allowing functions
# as default values.

def Struct(*args, **kwargs):
    FUNCTIONS = (types.BuiltinFunctionType, types.BuiltinMethodType, \
                 types.FunctionType, types.MethodType)
    def init(self, *iargs, **ikwargs):
        """Asume that unamed args are placed in the same order than
        astuple() yields (currently alphabetic order)
        """
        kw = list(self.__slots__)

        # set the unnamed args
        for i in range(len(iargs)):
            k = kw.pop(0)
            setattr(self, k, iargs[i])

        # set the named args
        for k, v in ikwargs.items():
            setattr(self, k, v)
            kw.remove(k)

        # set default values
        for k in kw:
            v = kwargs[k]
            if isinstance(v, FUNCTIONS):
                v = v()
            setattr(self, k, v)

    def astuple(self):
        return tuple([getattr(self, k) for k in self.__slots__])

    def __str__(self):
        data = ['{}={}'.format(k, getattr(self, k)) for k in self.__slots__]
        return '<{}: {}>'.format(self.__class__.__name__, ', '.join(data))

    def __repr__(self):
        return str(self)

    def __eq__(self, other):
        return self.astuple() == other.astuple()

    name = kwargs.pop("__name__", "MyStruct")
    slots = list(args)
    slots.extend(kwargs.keys())
    # set non-specific default values to None
    kwargs.update(dict((k, None) for k in args))

    return type(name, (object,), {
        '__init__': init,
        '__slots__': tuple(slots),
        'astuple': astuple,
        '__str__': __str__,
        '__repr__': __repr__,
        '__eq__': __eq__,
    })


Event = Struct('user', 'cmd', \
               'arg1', 'arg2',  \
               date=time.time, \
               __name__='Event')

aa = Event('pepe', 77)
print(aa)
raw = aa.astuple()

bb = Event(*raw)
print(bb)

if aa == bb:
    print('Are equals')

cc = Event(cmd='foo')
print(cc)

出力:

<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
Are equals
<Event: user=None, cmd=foo, arg1=None, arg2=None, date=1550051403.7938335>

0

答えはたくさんありますが、満足できる答えは見つかりませんでした。property動的なケースで機能する独自のソリューションを見つけました。元の質問に答えるソース:

#!/usr/local/bin/python3

INITS = { 'ab': 100, 'cd': 200 }

class DP(dict):
  def __init__(self):
    super().__init__()
    for k,v in INITS.items():
        self[k] = v 

def _dict_set(dp, key, value):
  dp[key] = value

for item in INITS.keys():
  setattr(
    DP,
    item,
    lambda key: property(
      lambda self: self[key], lambda self, value: _dict_set(self, key, value)
    )(item)
  )

a = DP()
print(a)  # {'ab': 100, 'cd': 200}
a.ab = 'ab100'
a.cd = False
print(a.ab, a.cd) # ab100 False

0

私にとってうまくいくものはこれです:

class C:
    def __init__(self):
        self._x=None

    def g(self):
        return self._x

    def s(self, x):
        self._x = x

    def d(self):
        del self._x

    def s2(self,x):
        self._x=x+x

    x=property(g,s,d)


c = C()
c.x="a"
print(c.x)

C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x)

出力

a
aa

-1

私は最近同様の問題に遭遇しました。私が思いついた解決策は、使用し__getattr____setattr__処理したいプロパティについては、他のすべてがオリジナルに渡されます。

class C(object):
    def __init__(self, properties):
        self.existing = "Still Here"
        self.properties = properties

    def __getattr__(self, name):
        if "properties" in self.__dict__ and name in self.properties:
            return self.properties[name] # Or call a function, etc
        return self.__dict__[name]

    def __setattr__(self, name, value):
        if "properties" in self.__dict__ and name in self.properties:
            self.properties[name] = value
        else:
            self.__dict__[name] = value

if __name__ == "__main__":
    my_properties = {'a':1, 'b':2, 'c':3}
    c = C(my_properties)
    assert c.a == 1
    assert c.existing == "Still Here"
    c.b = 10
    assert c.properties['b'] == 10

私はこれを調べましたが、技術的にはゲッターとセッターのヘルパーのリストを調べています。このため、直接アクセスするのではなく、最初にリストから検索しているため、各呼び出しは遅くなります。Pythonが自動でマッピングしない限り、可能性はありますが、確実に知るにはまだベンチマークしていませんが、試す前に心配です。次に、これを行うことにより、ヘルパーを別の方法で定義する必要があります。また、大規模なディクショナリや多くの余分な行を作成せずに、データ型や値をロックアウトすることもできません。
Acecool

つまり、システムを使用するすべての子を拡張する基本クラスを作成するか、すべてにs / getattrマジック関数を追加して、システムを毎回複製する必要があります。プロパティの宣言はまた、一方向でそれらを設定する必要があることを意味し、追加のサポートが必要な場合は、データの割り当てや他のヘルパーを許可または禁止するためのデータ型や値の保護などを記載しました、それからそれらをコード化する必要があります。当然のことながら、システムの動作を同様にすることもできますが、最終的にはわずかに異なる方法で大きく宣言することになります。
Acecool

-1

以下は、プログラムでプロパティオブジェクトを作成する簡単な例です。

#!/usr/bin/python3

class Counter:
    def __init__(self):
        cls = self.__class__
        self._count = 0
        cls.count = self.count_ref()

    def count_get(self):
        print(f'count_get: {self._count}')
        return self._count

    def count_set(self, value):
        self._count = value
        print(f'count_set: {self._count}')

    def count_del(self):
        print(f'count_del: {self._count}')

    def count_ref(self):
        cls = self.__class__
        return property(fget=cls.count_get, fset=cls.count_set, fdel=cls.count_del)

counter = Counter()

counter.count
for i in range(5):
    counter.count = i
del counter.count

'''
output
======
count_get: 0
count_set: 0
count_set: 1
count_set: 2
count_set: 3
count_set: 4
count_del: 4
'''

-2

プロパティを動的にアタッチする唯一の方法は、新しいクラスとそのインスタンスを新しいプロパティで作成することです。

class Holder: p = property(lambda x: vs[i], self.fn_readonly)
setattr(self, k, Holder().p)

1
これは機能していないようです。プロパティ自体ではなく、プロパティの結果を割り当てます。
mjallday 2013年

これは誤りです。クラスを初期化する必要なく、システムに動的プロパティをアタッチします。x = Example()として初期化してから、xにプロパティを追加します。
Acecool

私のコードを見ると、クラスExampleBase:pass、次にクラスExample(ExampleBase):...を使用していることがわかります。名前が存在し、Exampleがそれから拡張されているため、ExampleBaseにプロパティをアタッチします。すべてにアクセスできます。アクセサーヘルパーがアクセサーオブジェクトに直接アクセスできるようにするために__ varを使用します。格納されたデータ(raw)には_を使用します。これはNoneにすることができ、ゲッターを通過する実際のプロパティにはアンダースコアを使用しません。動的に追加された関数を使用してゲッター関数を呼び出すか、プロパティを使用できます。最初に初期化することなくすべて。
Acecool

注:言及しましたが、定義の私の定義は、参照が名前空間に存在することを意味します。つまり、クラスExample(Object):pass ...存在しますが、初期化されていません。初期化は、何とか= Example(); これでオブジェクトは「複製」および構築され、参照としてblahに保存されました。---これを行う場合、動的に追加される関数/プロパティはインスタンスにのみ存在する必要があります-これで私が抱えていた問題は、関数が存在していても、存在しないというエラーが発生する場合がありました。ブロッキングエラーが作成を停止したか、非同期実行されました。
Acecool

その他の注意事項:プロパティを動的に作成し、インスタンスごとにのみ存在するように機能させることができます。それらをオブジェクトに存在するように作成することもできます(ほとんどの場合これが必要です)。あなたが一つの領域に更新した場合、すべてが...同じ得る-と追加要素が「静的」、すなわち、同じ参照、であり、返される値は、すべてのインスタンス間で共有されている例がある
Acecool

-6

提供された回答の多くは、プロパティごとに非常に多くの行を必要とします。つまり、/および/または-複数のプロパティに必要な反復性などのために、醜い、または面倒な実装と見なすものです。簡略化することはできません、またはそれを行うための多くの目的を果たさなくなるまでは。

簡単に言うと、完成した作品で2行のコードを繰り返す場合、通常は1行のヘルパー関数に変換します。以下のように、数式や(start_x、start_y、end_x、end_y)などの奇数引数を簡略化します。 (x、y、w、h)すなわちx、y、x + w、y + h(min / maxが必要な場合、またはw / hが負で実装がそれを好まない場合は、x /から減算しますyおよびabs w / hなど)。

内部ゲッター/セッターをオーバーライドするのは良い方法ですが、問題は、すべてのクラスに対してそれを行うか、クラスをそのベースにペアレント化する必要があることです...私はそうしたくないので、私にはうまくいきません継承のための子/親、子ノードなどを自由に選択できます

私は、Dictデータ型を使用せずに質問に答えるソリューションを作成しました。データを入力するのが面倒であるなどの理由でデータを提供するためです...

私のソリューションでは、プロパティを追加するクラスの基本クラスを作成するために、クラスの上に2行を追加する必要があります。その後、1行ずつ追加し、コールバックを追加してデータを制御し、データが変更されたときに通知するオプションがあります。 、値やデータタイプなどに基づいて設定できるデータを制限します。

_object.x、_object.x = value、_object.GetX()、_ object.SetX(value)を使用するオプションもあり、それらは同等に処理されます。

さらに、値はクラスインスタンスに割り当てられる唯一の非静的データですが、実際のプロパティはクラスに割り当てられます。つまり、繰り返したくない、繰り返す必要がないことを意味します...デフォルト値を割り当てることができるので、デフォルトのデフォルト値をオーバーライドするオプションがありますが、ゲッターは毎回デフォルト値を必要としません。また、別のオプションがあるので、ゲッターはデフォルトのリターンをオーバーライドすることにより、生の保存値を返します(注:このメソッド生の値は、値が割り当てられた場合にのみ割り当てられることを意味します。それ以外の場合は、Noneです。値がリセットされると、Noneなどが割り当てられます。)

多くのヘルパー関数もあります-追加される最初のプロパティは、インスタンス値を参照するためにクラスに2つほどのヘルパーを追加します...それらは、ResetAccessors(_key、..)varargsの繰り返しです(すべて、最初の名前付き引数を使用して繰り返すことができます) )とSetAccessors(_key、_value)オプションを追加して、効率を上げるためにメインクラスに追加する-計画されているものは、アクセサをグループ化する方法です。そのため、一度にいくつかをリセットする傾向がある場合、名前付きキーを毎回繰り返す代わりに、それらをグループに割り当ててグループをリセットできます。

インスタンス/保存された生の値はクラスに保存されます。、 クラス。プロパティの静的変数/値/関数を保持するアクセサクラスを参照します。_クラス。設定/取得などの際にインスタンスクラスを介してアクセスされたときに呼び出されるプロパティ自体です。

アクセサー_class .__はクラスを指しますが、それは内部であるため、クラスに割り当てる必要があります。そのため、私は__Name = AccessorFunc(...)を使用してそれを割り当てることを選択しました。使用する引数(キー付き変数を使用すると、識別および保守が簡単かつ効率的になります)...

また、前述のように多くの関数を作成しますが、その一部はアクセサ関数情報を使用するため、呼び出す必要はありません(現時点では少し不便なので、_classを使用する必要があります。.FunctionName(_class_instance 、args)-このビットマラソンを実行する関数を追加するか、オブジェクトにアクセサーを追加してself(これを指すためにthisという名前を付ける)を追加することにより、スタック/トレースを使用してインスタンス参照を取得し、値を取得しました'インスタンス用であり、関数定義内からの自分、AccessorFuncクラス参照、およびその他の情報へのアクセスを保持します)。

それはまだ完全ではありませんが、素晴らしい足掛かりです。注:__Name = AccessorFunc(...)を使用してプロパティを作成しない場合、__キーにアクセスできなくなります。その場合、問題はありません。

また、名前とキーは異なることに注意してください...名前は「正式」で、関数名の作成で使用され、キーはデータの保存とアクセス用です。つまり、小文字のxがキーである_class.xの場合、名前は大文字のXになるため、GetX()が少し奇妙に見えるGetx()の代わりに関数になります。これにより、self.xが機能して適切に見えるようになるだけでなく、GetX()も適切に見えるようになります。

キー/名前が同じで、表示するクラスが異なるサンプルクラスを設定しています。データを出力するために作成された多くのヘルパー関数(注:これがすべて完了しているわけではありません)なので、何が起こっているのかを確認できます。

key:x、name:Xを使用する関数の現在のリストは、次のように出力されます。

これは決して包括的なリストではありません-投稿時にまだリストに載っていないものもいくつかあります...

_instance.SetAccessors( _key, _value [ , _key, _value ] .. )                   Instance Class Helper Function: Allows assigning many keys / values on a single line - useful for initial setup, or to minimize lines.    In short: Calls this.Set<Name>( _value ) for each _key / _value pairing.
_instance.ResetAccessors( _key [ , _key ] .. )                                 Instance Class Helper Function: Allows resetting many key stored values to None on a single line.                                           In short: Calls this.Reset<Name>() for each name provided.


Note: Functions below may list self.Get / Set / Name( _args ) - self is meant as the class instance reference in the cases below - coded as this in AccessorFuncBase Class.

this.GetX( _default_override = None, _ignore_defaults = False )                 GET:            Returns    IF ISSET: STORED_VALUE .. IF IGNORE_DEFAULTS: None  .. IF PROVIDED: DEFAULT_OVERRIDE ELSE: DEFAULT_VALUE       100
this.GetXRaw( )                                                                 RAW:            Returns    STORED_VALUE                                                                                                     100
this.IsXSet( )                                                                  ISSET:          Returns    ( STORED_VALUE != None )                                                                                         True

this.GetXToString( )                                                            GETSTR:         Returns    str( GET )                                                                                                       100
this.GetXLen( _default_override = None, _ignore_defaults = False )              LEN:            Returns    len( GET )                                                                                                       3
this.GetXLenToString( _default_override = None, _ignore_defaults = False )      LENSTR:         Returns    str( len( GET ) )                                                                                                3
this.GetXDefaultValue( )                                                        DEFAULT:        Returns    DEFAULT_VALUE                                                                                                    1111

this.GetXAccessor( )                                                            ACCESSOR:       Returns    ACCESSOR_REF ( self.__<key> )                                                                                    [ AccessorFuncBase ] Key: x : Class ID: 2231452344344 : self ID: 2231448283848        Default: 1111       Allowed Types: {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}     Allowed Values: None
this.GetXAllowedTypes( )                                                        ALLOWED_TYPES:  Returns    Allowed Data-Types                                                                                               {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}
this.GetXAllowedValues( )                                                       ALLOWED_VALUES: Returns    Allowed Values                                                                                                   None

this.GetXHelpers( )                                                             HELPERS:        Returns    Helper Functions String List - ie what you're reading now...                                                     THESE ROWS OF TEXT
this.GetXKeyOutput( )                                                           Returns information about this Name / Key                                                                                                   ROWS OF TEXT
this.GetXGetterOutput( )                                                        Returns information about this Name / Key                                                                                                   ROWS OF TEXT

this.SetX( _value )                                                             SET:            STORED_VALUE Setter - ie Redirect to __<Key>.Set                                                                            N / A
this.ResetX( )                                                                  RESET:          Resets STORED_VALUE to None                                                                                                 N / A

this.HasXGetterPrefix( )                                                        Returns Whether or Not this key has a Getter Prefix...                                                                                      True
this.GetXGetterPrefix( )                                                        Returns Getter Prefix...                                                                                                                    Get

this.GetXName( )                                                                Returns Accessor Name - Typically Formal / Title-Case                                                                                       X
this.GetXKey( )                                                                 Returns Accessor Property Key - Typically Lower-Case                                                                                        x
this.GetXAccessorKey( )                                                         Returns Accessor Key - This is to access internal functions, and static data...                                                             __x
this.GetXDataKey( )                                                             Returns Accessor Data-Storage Key - This is the location where the class instance value is stored..                                         _x

出力されるデータの一部は次のとおりです。

これは、Demoクラスを使用して作成されたまったく新しいクラス用であり、名前以外のデータが割り当てられていないため(出力できるため)、使用した変数名_fooです...

_foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016

    Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |

    Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    x:        1111                | _x:       None                     | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    y:        2222                | _y:       None                     | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    z:        3333                | _z:       None                     | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Blah:     <class 'int'>       | _Blah:    None                     | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Width:    1                   | _Width:   None                     | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Height:   0                   | _Height:  None                     | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    Depth:    2                   | _Depth:   None                     | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |


this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
this.IsXSet( ):       False     this.GetX( ):        1111                     this.GetXRaw( ):       None                     this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       4    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
this.IsYSet( ):       False     this.GetY( ):        2222                     this.GetYRaw( ):       None                     this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       4    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
this.IsZSet( ):       False     this.GetZ( ):        3333                     this.GetZRaw( ):       None                     this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       4    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
this.IsBlahSet( ):    False     this.GetBlah( ):     <class 'int'>            this.GetBlahRaw( ):    None                     this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    13   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
this.IsWidthSet( ):   False     this.GetWidth( ):    1                        this.GetWidthRaw( ):   None                     this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   1    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
this.IsDepthSet( ):   False     this.GetDepth( ):    2                        this.GetDepthRaw( ):   None                     this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
this.IsHeightSet( ):  False     this.GetHeight( ):   0                        this.GetHeightRaw( ):  None                     this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

そして、これはすべての_fooプロパティ(名前を除く)に同じ順序で次の値を割り当てた後です: 'string'、1.0、True、9、10、False

this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
this.IsXSet( ):       True      this.GetX( ):        10                       this.GetXRaw( ):       10                       this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       2    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
this.IsYSet( ):       True      this.GetY( ):        10                       this.GetYRaw( ):       10                       this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       2    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
this.IsZSet( ):       True      this.GetZ( ):        10                       this.GetZRaw( ):       10                       this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       2    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
this.IsBlahSet( ):    True      this.GetBlah( ):     string Blah              this.GetBlahRaw( ):    string Blah              this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    11   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
this.IsWidthSet( ):   True      this.GetWidth( ):    False                    this.GetWidthRaw( ):   False                    this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   5    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
this.IsDepthSet( ):   True      this.GetDepth( ):    9                        this.GetDepthRaw( ):   9                        this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
this.IsHeightSet( ):  True      this.GetHeight( ):   9                        this.GetHeightRaw( ):  9                        this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

_foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016

    Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |

    Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    x:        10                  | _x:       10                       | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    y:        10                  | _y:       10                       | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    z:        10                  | _z:       10                       | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Blah:     string Blah         | _Blah:    string Blah              | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Width:    False               | _Width:   False                    | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Height:   9                   | _Height:  9                        | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    Depth:    9                   | _Depth:   9                        | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |

制限されたデータ型または値の制限のため、一部のデータは割り当てられなかったことに注意してください-これは仕様によるものです。setterは、デフォルト値として割り当てられている場合でも、不適切なデータ型または値の割り当てを禁止します(デフォルト値の保護動作をオーバーライドしない限り)。

例と説明の後にスペースがなかったため、コードはここに掲載されていません...また、コードが変更されるためです。

注:この投稿の時点では、ファイルは乱雑です-これは変更されます。しかし、Sublime Textで実行してコンパイルするか、Pythonから実行すると、大量の情報がコンパイルされて吐き出されます-AccessorDB部分は実行されません(Print GetterおよびGetKeyOutputヘルパーの更新に使用されます)関数は、インスタンス関数に変更されるとともに、おそらく単一の関数に入れられて名前が変更されます-それを探してください。

次:実行にすべてが必要なわけではありません-下部にあるコメント付きのものの多くは、デバッグに使用される詳細情報用です-ダウンロードしたときに表示されない場合があります。その場合は、コメントを外して再コンパイルし、詳細情報を取得できます。

MyClassBase:pass、MyClass(MyClassBase):...が必要な回避策を探しています-解決策を知っている場合-投稿してください。

クラスで必要なのは__行のみです。strinitと同様にデバッグ用です。これらはデモクラスから削除できますが、以下の行の一部をコメント化または削除する必要があります(_foo / 2/3 )。

上部のString、Dict、およびUtilクラスは、私のPythonライブラリの一部です-完全ではありません。ライブラリから必要なものをいくつかコピーして、新しいものをいくつか作成しました。完全なコードは完全なライブラリにリンクし、更新された呼び出しの提供とコードの削除とともにそれを含めます(実際には、残っているコードは、デモクラスと印刷ステートメントだけです-AccessorFuncシステムはライブラリに移動されます)。 ..

ファイルの一部:

##
## MyClass Test AccessorFunc Implementation for Dynamic 1-line Parameters
##
class AccessorFuncDemoClassBase( ):
    pass
class AccessorFuncDemoClass( AccessorFuncDemoClassBase ):
    __Name      = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Name',      default = 'AccessorFuncDemoClass',  allowed_types = ( TYPE_STRING ),                    allowed_values = VALUE_ANY,                 documentation = 'Name Docs',        getter_prefix = 'Get',  key = 'Name',       allow_erroneous_default = False,    options = { } )
    __x         = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'X',         default = 1111,                     allowed_types = ( TYPE_INTEGER, TYPE_FLOAT ),       allowed_values = VALUE_ANY,                 documentation = 'X Docs',           getter_prefix = 'Get',  key = 'x',          allow_erroneous_default = False,    options = { } )
    __Height    = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Height',    default = 0,                        allowed_types = TYPE_INTEGER,                       allowed_values = VALUE_SINGLE_DIGITS,       documentation = 'Height Docs',      getter_prefix = 'Get',  key = 'Height',     allow_erroneous_default = False,    options = { } )

この美しさにより、AccessorFuncs /コールバック/データタイプ/値の強制などで動的に追加されるプロパティを持つ新しいクラスを非常に簡単に作成できます。

現時点では、リンクは(このリンクはドキュメントへの変更を反映している必要があります):https : //www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properties_accessorfuncs_and_more.py?dl=0

また、Sublime Textを使用しない場合は、適切なスレッド化の実装により、はるかに高速に使用できるため、Notepad ++、Atom、Visual Codeなどよりもお勧めします... IDEのようなコードにも取り組んでいますそのためのマッピングシステム-見てくださいhttps : //bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/(最初にパッケージマネージャーにリポジトリを追加してからプラグインをインストール-バージョン1.0.0の準備ができたら、追加しますそれをメインのプラグインリストに...)

この解決策がお役に立てば幸いです...そして、いつものように:

機能するからといって正しく機能しない-Josh 'Acecool' Moser


私は..あなたは、コードファイルが、コメントを開く必要はありませんので、それをサポートするためには表示されません。クラスがどのように見えるかをすばやく表示を追加したい
Acecool

どうやらこれは多くの嫌悪感を得ており、混乱しています。これは、OPが要求することを正確に実行します-オブジェクトにプロパティを動的に追加します。また、含まれている必要のないヘルパー関数も追加されます-おそらくそれがヘイトになっているのかもしれません-また、開発者がゲッターを通じて処理されるプロパティ(.x)に簡単にアクセスできるようにします格納された生の値(._x)は、.xがデフォルトまたはその他の何かを返したときにNoneになる可能性があり、ヘルパーを使用したり、物事を変更したりするためにアクセサーにアクセスする方法です。(.__ x)...
Acecool
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.