Как создать новый экземпляр из объекта класса в Python

#python #oop

#python #ооп

Вопрос:

Мне нужно динамически создать экземпляр класса в Python. По сути, я использую модуль load_module и inspect для импорта и загрузки класса в объект класса, но я не могу понять, как создать экземпляр этого объекта класса.

Комментарии:

1. Что? instance = Class()

2. Я предполагаю, что вы хотите динамически создавать новый класс. Не является объектом данного класса.

3. новый экземпляр означает новый объект со своим собственным пространством в памяти. большинство языков используют ключевое слово ‘new’, чтобы явно указать, что объект является новым и что на свойства нового экземпляра (object’s) нет ссылок / общего доступа к другому экземпляру.

4. Поскольку Python не использует ключевое слово «new», я обновил свой ответ ниже полным объяснением механизма создания класса.

Ответ №1:

Я выяснил ответ на возникший у меня вопрос, который привел меня на эту страницу. Поскольку никто на самом деле не предложил ответ на мой вопрос, я решил опубликовать его.

 class k:
  pass

a = k()
k2 = a.__class__
a2 = k2()
  

На данный момент a и a2 являются экземплярами одного и того же класса (class k).

Комментарии:

1. Кажется, это правильный ответ. Работает, и это просто.

2. Обратите внимание, что вы также можете передать параметры конструктору, если init их принимает a3 = k2(7)

3. В чем разница между k2 = a.__class__ и k2 = k ?

4. k2 является ли тип объекта, в данном случае тип de a ( a.__class ), k2() создающим новый экземпляр объекта этого типа, независимым от a . k2 = k просто создал бы новую ссылку на тот же экземпляр.

5. вы также можете получить class объект с помощью k2 = type(a) , а затем вызвать объект класса a2 = k2() . По сути, это то же самое, но вам не нужно засорять свой код этими уродливыми двойными подчеркиваниями … возможно, это также более переносимо

Ответ №2:

Просто вызовите встроенный «тип», используя три параметра, вот так:

 ClassName = type("ClassName", (Base1, Base2,...), classdictionary)
  

обновить
как указано в комментарии ниже, это вообще не ответ на этот вопрос. Я оставлю это неизмененным, поскольку есть подсказки, которые некоторые люди получают здесь, пытаясь динамически создавать классы — что и делает строка выше.

Для создания объекта класса у каждого тоже есть ссылка, как указано в принятом ответе, нужно просто вызвать класс:

 instance = ClassObject()
  

Механизм создания экземпляра, таким образом:

Python не использует new ключевое слово, используемое некоторыми языками — вместо этого его модель данных объясняет механизм, используемый для создания мгновенности класса, когда он вызывается с тем же синтаксисом, что и любой другой вызываемый:

Вызывается метод его класса’ __call__ (в случае класса его классом является «метакласс», который обычно является встроенным type ). Нормальным поведением этого вызова является вызов (псевдо) статического __new__ метода для создаваемого экземпляра класса, за которым следует его __init__ . __new__ Метод отвечает за выделение памяти и тому подобное, и обычно выполняется __new__ of object , который является корнем иерархии классов.

Таким образом, вызов ClassObject() вызывает ClassObject.__class__.call() (что обычно и будет type.__call__ ) этот __call__ метод получит сам ClassObject в качестве первого параметра — чистая реализация Python была бы такой: (версия CPython, конечно, выполнена на C и с большим количеством дополнительного кода для угловых регистров и оптимизации)

 class type:
    ...
    def __call__(cls, *args, **kw):
          constructor = getattr(cls, "__new__")
          instance = constructor(cls) if constructor is object.__new__ else constructor(cls, *args, **kw)
          instance.__init__(cls, *args, **kw)
          return instance
  

(Я не помню, чтобы видел в документах точное обоснование (или механизм) для подавления дополнительных параметров в корневом каталоге __new__ и передачи его другим классам — но это то, что происходит «в реальной жизни» — если object.__new__ вызывается с какими-либо дополнительными параметрами, это вызывает ошибку типа — однако любая пользовательская реализация __new__ получит дополнительные параметры нормально)

Комментарии:

1. Разве OP не хотел создать экземпляр, а не класс?

Ответ №3:

Вот как вы можете динамически создавать класс с именем, Child указанным в вашем коде, предполагая, что Parent он уже существует … даже если у вас нет явного Parent класса, вы могли бы использовать object

Приведенный ниже код определяет __init__() , а затем связывает его с классом.

 >>> child_name = "Child"
>>> child_parents = (Parent,)
>>> child body = """
def __init__(self, arg1):
    # Initialization for the Child class
    self.foo = do_something(arg1)
"""
>>> child_dict = {}
>>> exec(child_body, globals(), child_dict)
>>> childobj = type(child_name, child_parents, child_dict)
>>> childobj.__name__
'Child'
>>> childobj.__bases__
(<type 'object'>,)
>>> # Instantiating the new Child object...
>>> childinst = childobj()
>>> childinst
<__main__.Child object at 0x1c91710>
>>>
  

Ответ №4:

Если у вас есть модуль с классом, который вы хотите импортировать, вы можете сделать это следующим образом.

 module = __import__(filename)
instance = module.MyClass()
  

Если вы не знаете, как называется класс, вы можете выполнить итерацию по классам, доступным из модуля.

 import inspect
module = __import__(filename)
for c in module.__dict__.values():
    if inspect.isclass(c):
        # You may need do some additional checking to ensure 
        # it's the class you want
        instance = c()
  

Ответ №5:

Если у вас есть какой-либо объект класса, вы можете создать его экземпляр, просто вызвав его (в круглых скобках).

 class MyClass: pass        
some_class = MyClass    
some_instance = some_class() # -> instance of MyClass
  

Ответ №6:

Я думаю, что аккуратным способом было бы использовать type . Вот пример:

 >>> class Foo:
...     def __init__(self, s):
...       self.s = s
... 
>>> a = Foo("hello")
>>> a.s
'hello'
>>> b = type(a)("world")
>>> b.s
'world'
>>> assert isinstance(a, Foo)
>>> assert isinstance(b, Foo)
  

b это экземпляр, который имеет тот же тип, что и a .