web-dev-qa-db-ja.com

クラスメソッドから新しいクラスインスタンスを作成する

すでにインスタンス化されたオブジェクトのメソッドを呼び出すことにより、オブジェクトの新しいインスタンスを作成できるようにしたいと思います。たとえば、私はオブジェクトを持っています:

organism = Organism()

organism.reproduce()を呼び出して、Organism型の2つのオブジェクトを持つことができるようにしたいと思います。この時点での私の方法は次のようになります。

_class Organism(object):
    def reproduce():
        organism = Organism()
_

そして、私はそれが動作しないことをかなり確信しています(私はそれをどのようにテストするかさえ本当に確信がありません。 this post でgcメソッドを試しました)。それでは、オブジェクトに(organism = Organism()を使用して)最初に作成したオブジェクトと同じようにアクセス可能な自分自身のコピーを作成させるにはどうすればよいですか?

31
ohblahitsme
class Organism(object):
    def reproduce(self):
        #use self here to customize the new organism ...
        return Organism()

別のオプション-インスタンス(self)がメソッド内で使用されない場合:

class Organism(object):
    @classmethod
    def reproduce(cls):
        return cls()

これにより、生物はより多くの生物を生成し、(生物に由来する仮説的なボルグはより多くのボルグを生成します)。

selfを使用する必要がないという副次的な利点は、インスタンスから呼び出すことができることに加えて、クラスから直接呼び出すことができるようになったことです。

new_organism0 = Organism.reproduce()  # Creates a new organism
new_organism1 = new_organism0.reproduce()  # Also creates a new organism

最後に、インスタンス(self)とクラス(Organismまたはサブクラスから呼び出された場合はサブクラス)の両方がメソッド内で使用される場合:

class Organism(object):
    def reproduce(self):
        #use self here to customize the new organism ...
        return self.__class__()  # same as cls = type(self); return cls()

いずれの場合も、次のように使用します。

organism = Organism()
new_organism = organism.reproduce()
45
mgilson

このようなものはどうですか:

class Organism(object):

    population = []

    def __init__(self, name):
        self.name = name
        self.population.append(self)
    def have_one_child(self, name):
        return Organism(name)
    def reproduce(self, names):
        return [self.have_one_child(name) for name in names]

結果:

>>> a = Organism('a')
>>> len(Organism.population)
1
>>> a.reproduce(['x', 'y', 'z']) # when one organism reproduces, children are added
                                 # to the total population
                                 # organism produces as many children as you state
[<__main__.Organism object at 0x05F23190>, <__main__.Organism object at 0x05F230F0>, <__main__.Organism object at 0x05F23230>]
>>> for ele in Organism.population:
...     print ele.name
... 
a
x
y
z
>>> Organism.population[3].reproduce(['f', 'g'])
[<__main__.Organism object at 0x05F231D0>, <__main__.Organism object at 0x05F23290>]
>>> for ele in Organism.population:
...     print ele.name
... 
a
x
y
z
f
g
2
Akavall

単純にコピーモジュールを使用しないのはなぜですか?

import copy
organism = Organism()
replica = copy.deepcopy(organism)
1
jcr

元々同じ方法でしたが、それを使って何かをしなければなりません!

organism = Organism()はクラスOrganismを呼び出します(名前の直後の括弧は「呼び出し」操作です)。これにより、クラスの新しいインスタンスが作成されて返され、_organismという名前にバインドされます。

インタープリターでその行を実行すると、作成したばかりの新しいorganismインスタンスを参照する変数Organismがあります。

関数内にその行を書くと(メソッドと、「内部から」メソッドと関数に違いがないため)、同じことをしますが、変数organismlocal変数。関数が終了するとローカル変数は破棄されるため、これはdoesが新しいOrganismインスタンスを作成しますが、何も達成しません決してアクセスできないからです。

関数は、呼び出し元と通信したい情報をreturnする必要があります。返さないローカル変数は、それらの変数を使用してdoが返すものを作成する場合にのみ役立ちます。

これは、メソッド内にインスタンスを作成するという特定の問題に関連するnothingを持っていることに注意してください。それは関数/メソッドが一般的にどのように機能するかだけです。クラスとインスタンスを使用してオブジェクト指向プログラムを正常に作成するには、関数がどのように機能するかを学習する必要があります。いくつかのチュートリアルを進めることを強くお勧めします。

1
Ben
from copy import copy                                                           

class Organism(object):                                                         

    def __init__(self,name):                                                    
        self.name=name                                                          

    def setName(self,name):                                                     
        self.name=name                                                          

    def reproduce(self,childname):     
        #use deepcopy if necessary                                         
        cp = copy(self)                                                         
        cp.setName("descendant from " + self.name + " " + childname)            
        return cp                                                               

    def __str__(self):                                                          
        return self.name                                                        

first = Organism("first")                                                       
second = first.reproduce("second")                                              

print first                                                                     
print second 
0
RParadox