18

任意のデータをグループ化するために使用される 2 つの異なる Python オブジェクト、空のクラスと関数を見てきました。

def struct():
    pass

record = struct
record.number = 3
record.name = "Zoe"


class Struct:
    pass

record = Struct()
record.number = 3
record.name = "Zoe"

クラスが空でなくても、実行時に定義されている限り機能するようです。

しかし、生意気になって組み込みの関数やクラスでこれをやろうとすると、うまくいきませんでした。

record = set()
record.number = 3
AttributeError: 'set' object has no attribute 'number'

record = pow
pow.number = 3
AttributeError: 'builtin_function_or_method' object has no attribute 'number'

この動作を説明する組み込みクラスと「カスタム」クラスおよび関数の間に根本的な違いはありますか?

4

4 に答える 4

8

違いは、関数オブジェクトと Struct オブジェクトの両方に__dict__属性がありますが、setインスタンスと組み込み関数には属性がないことです。

>>> def struct():
...     pass
...
>>> record = struct
>>> record.number = 2
>>> struct.__dict__
{'number': 2}
>>> class Struct:
...     pass
...
>>> record = Struct()
>>> record.number = 3
>>> record.__dict__
{'number': 3}
>>> record=set()
>>> record.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'set' object has no attribute '__dict__'
>>> pow.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__dict__'

クラスでは、スロットを使用して動作をエミュレートできます (ただし、新しいスタイルのクラスのみ)。

>>> class StructWithSlots(object):
...     __slots__ = []
...
>>> record = StructWithSlots()
>>> record.number = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'StructWithSlots' object has no attribute 'number'
>>> record.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'StructWithSlots' object has no attribute '__dict__'
于 2013-07-11T14:32:16.560 に答える
2

一部のビルトインは、より制限的である場合があります。また、スロットで実装されたクラスも任意の属性を受け入れません。

于 2013-07-11T13:55:35.840 に答える
1

独自のクラスでシミュレート保護が必要な場合は、__setattr__()メソッドを使用できます。

class TestClass(object):
    # Accept the attributes in this list
    __valid_attributes = ["myattr1", "myattr2"]

    def __setattr__(self, name, value):
        if not name in TestClass.__valid_attributes:
            raise AttributeError(
                "{0} has no attribute '{1}'".format(self.__class__.__name__, name))
        self.__dict__[name] = value

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

t = TestClass()
t.noattr = "test" # AttributeError: TestClass has no attribute 'noattr'

ただし、「有効な属性」は引き続き設定できます。

t = TestClass()
t.myattr1 = "test"
print(t.myattr1) # test
于 2013-07-11T14:23:12.963 に答える