Python Instantiate Class Within Class Definition

前端 未结 4 954
小蘑菇
小蘑菇 2021-01-14 14:14

I am attempting to add a variable to a class that holds instances to the class. The following is a shortened version of my code.

class Classy :
    def __in         


        
相关标签:
4条回答
  • 2021-01-14 14:46

    The class body is executed before the class is created. Therefore, you are attempting the instantiate the class before it exists. You can still attach instances to the class, but you have to create them after the class body finished, e.g.:

    class Classy(object):
        def __init__(self):
            self.hi = "HI!"
        CLASSIES = []
    
    for i in xrange(4):
        Classy.CLASSIES.append(Classy())
    

    However, I'd suggest you first think long and hard whether you actually need this effectively-global list, and whether you need it to be part of the class object. Personally, I almost never do something like this.

    0 讨论(0)
  • 2021-01-14 14:52

    The simplest way to do this is do it after the class is created, when the class has been defined, and therefore can be used:

    class Classy :
        CLASSIES = []
    
        def __init__(self) :
            self.hi = "HI!"
    
    Classy.CLASSIES = [Classy() for _ in xrange(0,4)]
    

    (Here using a list comprehension for convinience, as it's the most readable and efficent way to build a list).

    Also note that if this intended to be a constant, you should probably make it a tuple rather than a list, and if it isn't intended to be, you should probably not use an ALL_CAPS name which, by convention, implies a constant.

    0 讨论(0)
  • 2021-01-14 14:55

    It seems to me that you want to obtain that:

    class Classy :
        CLASSIES = []
        def __init__(self) :
            self.hi = "HI!"
            Classy.CLASSIES.append(self)
    
    for i in xrange(4):
        Classy()
    
    for x in  Classy.CLASSIES:
        print x
    

    result

    <__main__.Classy instance at 0x011DF3F0>
    <__main__.Classy instance at 0x011DF440>
    <__main__.Classy instance at 0x011DF418>
    <__main__.Classy instance at 0x011DF2B0>
    

    EDIT

    Note that with the code of Lattyware:

    class Classy :
        CLASSIES = []
        idC = id(CLASSIES)
        def __init__(self) :
            self.hi = "HI!"
            #Classy.CLASSIES.append(self)
    
    
    Classy.CLASSIES = [Classy() for _ in xrange(0,4)]
    
    print Classy.idC
    print id(Classy.CLASSIES)
    print 'Classy.idC==id(Classy.CLASSIES) :',Classy.idC==id(Classy.CLASSIES)
    

    result

    18713576
    10755928
    Classy.idC==id(Classy.CLASSIES) : False
    

    While with the for loop of delnan'code, it doesn't appear.

    However it's easy to correct:
    writing
    Classy.CLASSIES[:] = [Classy() for _ in xrange(0,4)]
    or
    Classy.CLASSIES.extend(Classy() for _ in xrange(0,4))
    instead of
    Classy.CLASSIES = [Classy() for _ in xrange(0,4)]
    it depends of what is desired.

    EDIT 2

    Methods may reference global names in the same way as ordinary functions. The global scope associated with a method is the module containing its definition. (A class is never used as a global scope.)

    http://docs.python.org/2/tutorial/classes.html#class-definition-syntax

    A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g., C.x is translated to C.__dict__["x"]

    http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes

    class Classy :
        CLASSIES = []
    
    print '"CLASSIES" in globals()',"CLASSIES" in globals()
    print '"CLASSIES" in Classy.__dict__ ==',"CLASSIES" in Classy.__dict__
    

    result

    "CLASSIES" in globals() False
    "CLASSIES" in Classy.__dict__ == True
    

    Delnan, how will you continue to pretend that CLASSIES is global ??
    Did I misunderstood something in your debate with Lattyware ?

    0 讨论(0)
  • 2021-01-14 15:01

    The class itself is not defined until after the class block finishes executing, so you can't make use of the class inside its own definition.

    You could use a class decorator or a metaclass to add your desired class variable after the class is created. Here's an example with a decorator.

    def addClassy(cls):
        cls.CLASSIES = [cls() for a in xrange(4)]
        return cls
    
    @addClassy
    class Classy(object):
        pass
    
    >>> Classy.CLASSIES
    0: [<__main__.Classy object at 0x000000000289A240>,
     <__main__.Classy object at 0x000000000289A518>,
     <__main__.Classy object at 0x000000000289A198>,
     <__main__.Classy object at 0x000000000289A208>]
    
    0 讨论(0)
提交回复
热议问题