클래스에 동적으로 속성을 추가하는 방법은 무엇입니까?


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])것은 전혀 쓸모 가 없습니다.

런타임에 인스턴스 속성을 만드는 올바른 방법은 무엇입니까?

추신 : 나는 방법이 어떻게 사용됩니까?에 제시된 대안을 알고 있습니다 .__getattribute__


2
코드에는 오타가 있습니다. fn_readonly의 정의에는 a :__init__reference가 필요합니다 self.fn_readyonly.
mhawke

네 말이 맞아 런타임에 속성을 만드는 이유를 강조하기 위해 마지막 순간에 해당 setter 함수를 추가했습니다.
Anthony Kong

초기화시 속성을 만드는 데있어 주요한 문제는 경우에 따라 도우미를 빨리 호출하거나 문제가 발생하면 실제로도 불구하고 존재하지 않았다는 오류가 발생한다는 것입니다. 아래 솔루션에서 2 개의 클래스를 만듭니다. 하나는 Base / Parent (피할 솔루션을 찾으려고 노력하고 있음) 및 Base / Parent를 확장하는 기본 객체입니다. 그런 다음 기본 객체에서 초기화하지 않고 속성, 도우미 함수 등을 만드는 AccessorFunc 작성자를 호출합니다.
Acecool

예 : class ExampleBase : pass; 클래스 Example (ExampleBase) : __x = 접근 자 (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

다음은 동적 속성 및 동적 함수를 생성하는 기본 버전에 대한 링크입니다. 파일에는 다른 버전에 대한 링크가 많이 있습니다. 하나는 헬퍼를 생성하는 함수를 사용하는 AccessorFunc 시스템입니다 (하나는 함수, 하나는 속성, 하나는 개별 요소로 사용). 파일에 어떤 것도 코드 단축을 사용하지 않습니다. 다른 파일은 있습니다 dropbox.com/s/phnnuavssmzeqrr/dynamic_properties_simple.py?dl=0
Acecool

답변:


333

나는이 대답을 확장해야한다고 생각합니다. 이제 나이가 많고 현명하고 진행 상황을 알고 있습니다. 안하는 것보다 늦게하는 것이 낫다.

당신은 할 수 클래스 동적에 속성을 추가 할 수 있습니다. 그러나 그것은 캐치입니다. 클래스 에 추가해야합니다 .

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

A property는 실제로 descriptor 라고하는 것의 간단한 구현입니다 . 주어진 클래스에서 주어진 속성에 대한 사용자 정의 처리를 제공하는 객체입니다 . 큰 if나무를 제거 하는 방법을 좋아합니다 __getattribute__.

내가 부탁하면 foo.b위의 예에서, 파이썬은 있다고 본다 b클래스 구현에 정의 된 기술자 프로토콜 단지가와 객체의 의미 - 어떤 __get__, __set__또는 __delete__방법을. 설명자는 해당 속성을 처리 할 책임이 있다고 주장하므로 Python은 호출 Foo.b.__get__(foo, Foo)하고 반환 값은 속성 값으로 다시 전달됩니다. 의 경우 property, 이러한 각각의 방법은 바로 호출 fget, fset또는 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>

겸손한 방법은 또 다른 종류의 설명자입니다. 그 __get__첫 번째 인수로 호출 인스턴스 침; 사실상, 이렇게합니다 :

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

어쨌든, 이것이 디스크립터가 클래스에서만 작동하는 이유라고 생각합니다. 그것들은 규칙에 대한 예외이기도합니다 type. 분명히 기술자를 클래스에 할당 할 수 있으며 클래스 자체는 인스턴스입니다 ! 실제로, Foo.b여전히 전화 를 읽으려고 노력 property.__get__; 클래스 속성으로 액세스 할 때 설명자가 자신을 반환하는 것은 관용적입니다.

거의 모든 파이썬의 OO 시스템이 파이썬으로 표현 될 수 있다는 것은 멋진 일이라고 생각합니다. :)

아, 그리고 당신이 관심이 있다면 한동안 설명자관한 간단한 블로그 게시물을 썼습니다 .


35
add_property 메소드를 추가 할 필요가 없습니다. setattr (Foo, 'name', property (func))
코트니 D

8
당신의 "그러나 그것은 캐치입니다 ..."방금 몇 시간의 작업을 저장했습니다. 감사합니다.
Matt Howell

2
단일 인스턴스에서 특성을 정의하려는 경우 런타임시 클래스를 작성하고 __class__를 수정할있습니다 .
Wilfred Hughes

1
@ myproperty.setter는 어떻습니까? 그것을 동적으로 추가하는 방법?
LRMAAX

초기화 된 객체에 속성을 추가 할 필요는 없습니다. 그렇게하면 인스턴스에만 충실한다는 것을 의미하지만 다시 확인해야합니다. 나는 동적 속성이 인스턴스 일뿐 인 비슷한 문제에 부딪쳤다는 것을 알고 있으며 정적 설정과 객체에 대한 것이기 때문에 나중에 초기화 할 때 사용할 수 있습니다. 내 게시물은 아래에 있으며 도우미 기능과 모든 것에 쉽게 액세스 할 수있는 쉬운 방법을 만듭니다. 속성의 경우 .x, getter / setter가 사용하는 원시 데이터 (._x) 및 접근 자 개체의 .__ x
Acecool

57

목표는 DB 결과 집합처럼 동작하는 모의 클래스를 만드는 것입니다.

그래서 당신이 원하는 것은 a [ 'b']를 ab로 철자 할 수있는 사전입니까?

쉽습니다.

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

1
보다 일반적인 설정에서는 제한적인 용도로 사용됩니다. dict에 d = { 'a1': { 'b': 'c'}, 'a2': ...}와 같은 다단계 계층 구조가있는 경우 d.a1 또는 d.a2를 수행 할 수는 있지만 ' t do d.a1.b
Shreyas

1
한 가지 유념해야 할 점은이 DICT 방법 또는 속성과 같은 이름을 가진 속성에 대한 속성 값을 설정할 수 있다는 것입니다,하지만 같은 방식으로 다시 값을 검색하는 것을 허용하지 않습니다 d.items = 1, d.items반환 <built-in method items of atdict object at ...>. 대신을 대신 d["items"]사용하거나 사용할 수는 있지만 대부분의 dict 방법을 사용 하지 못합니다 . __getattribute____getattr__
Marcono1234

뭉크 라이브러리를 사용하십시오 ! (무리의 포크)
브라이언 피터슨

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()인스턴스에서는 작동하지 않습니다.


좋은 생각이야 불행히도 현재 파이썬 2.4에 갇혀 있습니다.
Anthony Kong


2
글을 쓴 사람은 namedtuple충실하고 사물 지향적 인 원칙으로 매끄럽고 우아하게 만든 상을받을 가치가 있습니다.
Keith Pinson

4
죄송합니다.이 답변은 읽기 전용 속성으로 만 구성된 클래스를 모두 미리 알고있는 특수한 경우에만 적용 할 수 있습니다. 다시 말해, 런타임에 클래스에 일반 속성 (읽기 전용 속성이 아닌)을 추가하는 방법에 대한 광범위한 질문을 다루지 않는다고 생각합니다 (다른 "추가 기능"의 현재 버전도 마찬가지입니다) 저자에 의해 게시).
martineau

@martineau 그래서 ...에 더 많은 인수를 전달 property()? 읽기 전용 속성에만 해당되는 답변은 없습니다.
Eevee

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

파이썬 클래스에 동적으로 속성을 추가하는 방법은 무엇입니까?

속성을 추가하려는 객체가 있다고 가정하십시오. 일반적으로 일관된 API를 유지할 수 있도록 다운 스트림 사용 코드의 속성에 대한 액세스 관리를 시작해야 할 때 속성을 사용하고 싶습니다. 이제는 일반적으로 객체가 정의 된 소스 코드에 추가하지만 액세스 권한이 없거나 프로그래밍 방식으로 함수를 동적으로 선택해야한다고 가정 해 보겠습니다.

수업 만들기

에 대한 문서를property 기반으로 한 예제를 사용하여 "hidden"속성을 가진 객체 클래스를 만들고 인스턴스를 만들어 봅시다.

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

o = C()

파이썬에서는 일을하는 확실한 방법이있을 것으로 기대합니다. 그러나이 경우 데코레이터 표기법과없는 두 가지 방법을 보여 드리겠습니다. 먼저 데코레이터 표기법이 없습니다. 게터, 세터 또는 삭제 기의 동적 할당에 더 유용 할 수 있습니다.

동적 (일명 원숭이 패치)

우리 수업을 위해 몇 가지를 만들어 봅시다 :

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

그리고 프로비저닝 된 setter 및 deleter가있는 특성 오브젝트를 클래스에 지정하십시오.

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

이 스택 오버플로 게시물에 비슷한 질문을 하여 간단한 유형을 만든 클래스 팩토리를 만들었습니다. 결과는 클래스 팩토리의 작동 버전이있는 이 답변 이었습니다 . 다음은 답변의 스 니펫입니다.

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
Allan Karlson

4

검색 엔진에서 오는 사람들을 위해 동적 속성 에 대해 이야기 할 때 찾고 있던 두 가지가 있습니다.

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 콤보는 위의 예와 같이 클래스에 저장된 데이터에 대한 액세스를 단순화하는 데 좋습니다.

하나의 동적 속성 만 원한다면 property () 내장 함수를 살펴보십시오 .


4

property()속성은 데이터 설명자이므로 런타임에 인스턴스에 새 항목 을 추가 할 수 없습니다 . 대신 __getattribute__인스턴스에서 데이터 디스크립터를 처리하려면 새 클래스를 동적으로 작성하거나 과부하해야합니다 .


이것은 잘못이다. 속성을 클래스에 추가 한 다음 메소드에서 액세스 할 수 있습니다.
Ahmed

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

원하는 효과를 얻는 방법의 또 다른 예

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에서 from 을 사용 collections하여이를 수행 하는 방법을 보여 드리겠습니다 .

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

나는 이것을 조사했지만 기술적으로 getter 및 setter 도우미의 목록을 검토하고 있습니다. 이 때문에 먼저 직접 액세스하지 않고 목록에서 조회하기 때문에 각 통화가 느려집니다. 파이썬이 자동으로 매핑하지 않는 한; 그럴지도 모르지만 아직 벤치마킹하지는 않았지만 시도하기 전에 관심이 있습니다. 둘째, 이렇게하면 도우미를 다른 방법으로 정의해야합니다. 또한 큰 사전이나 많은 추가 줄로 끝나지 않으면 데이터 유형 및 / 또는 값을 잠글 수 없습니다.
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

이것은 올바르지 않습니다. 클래스를 초기화 할 필요없이 시스템에 동적 속성을 연결합니다. x = Example ()로 초기화 한 다음 x에 속성을 추가하십시오.
Acecool

내 코드를 살펴보면 ExampleBase : pass 클래스를 사용한 다음 Example Example (ExampleBase) : ... 클래스를 사용한다는 것을 알 수 있습니다. 그런 다음 이름이 존재하기 때문에 ExampleBase에 속성을 연결하고 Example이 코드에서 그것은 모든 것에 접근 할 수 있습니다. 접근 자 헬퍼가 접근 자 객체에 직접 액세스 할 수 있도록 __ var를 사용하고, 저장된 데이터 (raw)에 대해 _를 사용하고 None은 가능하며 getter를 통과하는 실제 속성에는 밑줄이 없습니다. 동적으로 추가 된 함수를 사용하여 getter 함수를 호출하거나 속성을 사용할 수 있습니다. 처음 시작하지 않고 모두.
Acecool

참고 : 언급했지만 정의에 대한 내 정의는 네임 스페이스에 참조가 있음을 의미합니다. 예 : class Example (Object) : pass ... 존재하지만 초기화되지 않았습니다. 초기화는 blah = Example (); 이제 객체가 '중복'되어 구성되었으며 참조로 blah에 저장되었습니다. --- 이렇게하면 동적으로 추가 된 함수 / 속성이 인스턴스에만 있어야합니다.이 문제는 함수가 존재하더라도 오류가 발생했다는 오류가 발생했습니다. 차단 오류가 생성을 중지했거나 비동기 실행입니다.
Acecool

기타 참고 사항 : 속성을 동적으로 생성 할 수 있으며 인스턴스 당 존재하는 방식으로 작동합니다. 또한 객체 (대부분의 경우 원하는 것)에 대해 존재하도록 만들 수도 있습니다. 추가 된 요소가 '정적'인 경우, 즉 동일한 참조, 반환 된 값이 모든 인스턴스에서 공유되는 경우가 있습니다. 한 영역에서 업데이트하면 모두 같은 결과를 얻습니다.
Acecool

-6

제공된 답변을 많이 얻으려면 속성 당 너무 많은 줄이 필요합니다. 즉, 여러 속성에 필요한 반복성으로 인해 추악하거나 지루한 구현이라고 생각합니다. 더 이상 단순화 할 수 없거나 그렇게 할 목적이 없을 때까지

간단히 말하면, 완성 된 작품에서 2 줄의 코드를 반복하면 일반적으로 한 줄 도우미 함수로 변환하는 등의 식으로 시작합니다. (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)를 사용하는 옵션도 있으며 동등하게 처리됩니다.

또한 값은 클래스 인스턴스에 할당 된 비 정적 데이터 만 유일하지만 실제 속성은 클래스에 할당되어 반복하고 싶지 않으며 반복 할 필요가없는 것을 의미합니다. 기본 기본값을 재정의하는 옵션이 있지만 getter가 매번 필요하지 않도록 기본값을 할당 할 수 있으며 다른 옵션이 있으므로 getter가 기본 반환 값을 재정 의하여 원시 저장된 값을 반환합니다 (참고 :이 방법 값이 할당 될 때만 원시 값이 할당되고 그렇지 않으면 None입니다. 값이 Reset 인 경우 None 등이 할당됩니다.)

많은 도우미 함수도 있습니다-추가되는 첫 번째 속성은 인스턴스 값을 참조하기 위해 클래스에 도우미를 2 개 정도 추가합니다 ... 이들은 ResetAccessors (_key, ..) varargs입니다 (모두 첫 번째 명명 된 인수를 사용하여 반복 할 수 있음) ) 및 SetAccessors (_key, _value)는 효율성을 높이기 위해 메인 클래스에 추가되는 옵션이 있습니다. 계획된 방법은 다음과 같습니다. 접근자를 그룹화하는 방법입니다. 따라서 매번 몇 번 재설정하는 경향이 있습니다. , 매번 이름 지정된 키를 반복하는 대신 그룹에 할당하고 그룹을 재설정 할 수 있습니다.

인스턴스 / 원시 저장 값은 클래스에 저장됩니다 ., 클래스. 속성에 대한 정적 변수 / 값 / 함수를 보유하는 접근 자 클래스를 참조합니다. _수업. 설정 / 가져 오기 등의 동안 인스턴스 클래스를 통해 액세스 할 때 호출되는 속성 자체입니다.

접근 자 _class .__은 클래스를 가리 키지 만 내부적으로 클래스에 할당해야하기 때문에 __Name = AccessorFunc (...)를 사용하여 할당합니다. 사용할 인수 (키워드 된 varargs를 사용하면 더 쉽고 효율적으로 식별하고 유지 관리 할 수 ​​있음) ...

또한 언급 한 것처럼 많은 함수를 작성합니다. 일부 함수접근 자 함수 정보 를 사용 하므로 호출 할 필요가 없습니다 (지금은 약간 불편하므로 _class를 사용해야합니다. .FunctionName (_class_instance , args)-스택 / 추적을 사용 하여이 비트 마라톤을 실행하는 함수를 추가하거나 객체에 접근자를 추가하고 self를 사용하여 값을 가져 오기 위해 인스턴스 참조를 가져옵니다. '인스턴스를위한 것이며 함수 정의 내에서 self, AccessorFunc 클래스 참조 및 기타 정보에 대한 액세스 권한을 유지해야합니다.

아직 완료되지는 않았지만 환상적인 발판입니다. 참고 : 속성을 만드는 데 __Name = AccessorFunc (...)를 사용하지 않으면 init 함수 내에서 정의하더라도 __ 키에 액세스 할 수 없습니다. 그렇게하면 아무런 문제가 없습니다.

또한 : 이름과 키가 다르다는 점에 유의하십시오. 이름은 '형식적'이며 기능 이름 작성에 사용되며 키는 데이터 저장 및 액세스를위한 것입니다. 즉, 소문자 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)

그리고 이것은 'string', 1.0, True, 9, 10, False와 같은 순서로 모든 _foo 속성 (name 제외)에 다음 값을 할당 한 후입니다.

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)                                                                                                                                                                                                   |

제한된 데이터 유형 또는 값 제한으로 인해 일부 데이터가 할당되지 않았습니다. 이것은 의도적으로 설계된 것입니다. 세터는 잘못된 데이터 유형 또는 값이 기본값으로 지정되지 않은 경우 (기본값 보호 동작을 무시하지 않는 한) 금지합니다.

예제와 설명 뒤에 여유가 없었기 때문에 코드가 게시되지 않았습니다 ... 또한 변경 될 것입니다.

참고 :이 게시물을 게시 할 때 파일이 지저분합니다-변경됩니다. 그러나 Sublime Text에서 실행하고 컴파일하거나 Python에서 실행하면 많은 정보를 컴파일하고 뱉어냅니다 .AccessorDB 부분은 수행되지 않습니다 (인쇄 Getter 및 GetKeyOutput 도우미를 업데이트하는 데 사용됨) 함수를 인스턴스 함수로 변경하고 단일 함수에 넣고 이름을 바꿉니다.)

다음 : 실행에 필요한 모든 것은 아닙니다. 하단에 주석이 달린 많은 부분은 디버깅에 사용되는 자세한 정보를위한 것입니다. 다운로드 할 때 없을 수도 있습니다. 그렇다면 주석 처리를 해제하고 다시 컴파일하여 자세한 정보를 얻을 수 있어야합니다.

MyClassBase : pass, MyClass (MyClassBase) : ...-해결 방법을 알고 있다면 게시하십시오.

클래스에 필요한 유일한 것은 __ 줄입니다. str초기화 와 마찬가지로 디버깅 입니다. 데모 클래스에서 제거 할 수 있지만 아래 줄을 주석 처리하거나 제거해야합니다 (_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를 사용하지 않으면 적절한 스레딩 구현으로 인해 메모장 ++, Atom, Visual Code 및 기타를 사용하는 것이 좋습니다. 사용하기 훨씬 훨씬 빠릅니다. 나는 IDE와 같은 코드로 작업하고 있습니다. 그것을 위해 매핑 시스템 - 한 번 봐 걸릴 : https://bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/은 - 버전 1.0.0가 준비되면, 내가 추가 할 것 (다음 설치를 먼저 패키지 관리자에서 플러그인을 리포 추가 메인 플러그인 목록으로 ...)

이 솔루션이 도움이 되길 바랍니다.

Josh 'Acecool'Moser


코드 파일을 열 필요는 없지만 주석이이를 지원하지 않는 것처럼 보입니다.
Acecool

분명히 이것은 많은 미움을 받고 있으며, 이는 혼란 스럽습니다. 그것은 OP가 요구하는 것을 정확하게 수행합니다-객체에 속성을 동적으로 추가합니다. 또한 포함 할 필요가없는 도우미 기능을 추가합니다. 아마도 싫어하는 이유입니다. 개발자가 게터를 통해 처리되는 속성 (.x)에 쉽게 액세스 할 수 있도록합니다. .x가 기본값이나 다른 것을 반환 할 때 None이 될 수있는 원시 값 저장 (._x) 및 도우미를 사용하거나 도우미 등을 변경하기 위해 접근 자에 액세스하는 방법입니다. (.__ x) ....
Acecool
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.