Створення порожнього об'єкта в Python


77

Чи існують ярлики для визначення порожнього об'єкта в Python, чи завжди потрібно створювати екземпляр власного порожнього класу?

Редагувати: Я маю на увазі порожній об’єкт, придатний для набору качок.

Відповіді:


102

Ви можете використовувати type, щоб створити новий клас на льоту, а потім створити його екземпляр. Подобається так:

>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>

Аргументами для введення є: ім'я класу, сукупність базових класів та словник об'єкта. Які можуть містити функції (методи об’єкта) або атрибути.

Ви можете фактично скоротити перший рядок до

>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)

Оскільки за замовчуванням тип створює нові класи стилів, які успадковуються від об'єкта.

typeвикористовується в Python для метапрограмування .

Але якщо ви просто хочете створити екземпляр об’єкта. Потім просто створіть його екземпляр. Як пропонує lejlot.

Створення екземпляру нового класу, подібного до цього, має важливу відмінність, яка може бути корисною.

>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'

Де як:

>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>> 

75

Так, у Python 3.3 було додано SimpleNamespace

На відміну від об'єкта, за допомогою SimpleNamespace ви можете додавати та видаляти атрибути. Якщо об’єкт SimpleNamespace ініціалізується аргументами ключового слова, вони безпосередньо додаються до базового простору імен.

Приклад:

import types

x = types.SimpleNamespace()
x.happy = True

print(x.happy) # True

del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'

48

Один простий, менш жахливий на вигляд спосіб створити порожній (-ish) об'єкт - використати той факт, що функції є об'єктами в Python, включаючи Lambda Functions:

obj = lambda: None
obj.test = "Hello, world!"

Наприклад:

In [18]: x = lambda: None

In [19]: x.test = "Hello, world!"

In [20]: x.test
Out[20]: 'Hello, world!'

Мені подобається це рішення, тому що не потрібно
Х'ю Перкінс

4
Хм-м-м, але у вас є мінус, який ви не можете призначитиx.__class__.somefunc
Х'ю Перкінс

1
це рішення має проблему, коли я намагаюся скопіювати.deepcopy () цей об'єкт. types.SimpleNamespace () у python 3 - найкраще рішення.
cn123h

12

Що ви маєте на увазі під "порожнім об'єктом"? Екземпляр класу object? Ви можете просто бігати

a = object()

чи, можливо, ви маєте на увазі ініціалізацію до нульового посилання? Тоді можна використовувати

a = None

21
Цікаво, що OP зможе зробити з aвизначеним або як, object()або Noneтому, що в таких випадках aнемає простору імен, __dict__і жоден атрибут не може бути доданий до aподібного, наприклад a.x = 10.
eyquem

1
Дійсно, a = object(); a.foo = 'bar'дає AttributeError: 'object' object has no attribute 'foo'.
Бас

3

Усі запропоновані рішення є дещо незграбними.

Я знайшов спосіб, який не є хакі, але насправді відповідає оригінальному дизайну.

>>> from mock import Mock
>>> foo = Mock(spec=['foo'], foo='foo')
>>> foo.foo
'foo'
>>> foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../virtualenv/local/lib/python2.7/site-packages/mock/mock.py", line 698, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'

Дивіться документацію до unittest.mock тут.


1

Конструює новий порожній об'єкт Set . Якщо надано необов’язковий ітерабельний параметр, оновлює набір елементами, отриманими в результаті ітерації. Всі елементи, що містять ітерацію, повинні бути незмінними або перетворюватися на незмінну, використовуючи протокол, описаний у розділі Протокол для автоматичного перетворення в незмінний.

Приклад:

myobj = set()
for i in range(1,10): myobj.add(i)
print(myobj)

1

Ви сказали це у запитанні, але оскільки жодна відповідь не згадувала про це за допомогою коду, це, мабуть, одне з найчистіших рішень:

class Myobject:
    pass

x = Myobject()
x.test = "Hello, world!"  # working


1

Можна використовувати

x = lambda: [p for p in x.__dict__.keys()]

Тоді

x.p1 = 2
x.p2 = "Another property"

Після

x()
# gives
# ['p1', 'p2']

І

[(p, getattr(x,p)) for p in x()]
# gives
# [('p1', 2), ('p2', 'Another property')]

0

На мій погляд, найпростіший спосіб:

def x():pass
x.test = 'Hello, world!'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.