Python Class vs. Module Attributes

前端 未结 4 717
抹茶落季
抹茶落季 2020-12-29 09:47

I\'m interested in hearing some discussion about class attributes in Python. For example, what is a good use case for class attributes? For the most part, I can not come up

相关标签:
4条回答
  • 2020-12-29 10:21

    #4: I never use class attributes to initialize default instance attributes (the ones you normally put in __init__). For example:

    class Obj(object):
        def __init__(self):
            self.users = 0
    

    and never:

    class Obj(object):
        users = 0
    

    Why? Because it's inconsistent: it doesn't do what you want when you assign anything but an invariant object:

    class Obj(object):
        users = []
    

    causes the users list to be shared across all objects, which in this case isn't wanted. It's confusing to split these into class attributes and assignments in __init__ depending on their type, so I always put them all in __init__, which I find clearer anyway.


    As for the rest, I generally put class-specific values inside the class. This isn't so much because globals are "evil"--they're not so big a deal as in some languages, because they're still scoped to the module, unless the module itself is too big--but if external code wants to access them, it's handy to have all of the relevant values in one place. For example, in module.py:

    class Obj(object):
        class Exception(Exception): pass
        ...
    

    and then:

    from module import Obj
    
    try:
        o = Obj()
        o.go()
    except o.Exception:
        print "error"
    

    Aside from allowing subclasses to change the value (which isn't always wanted anyway), it means I don't have to laboriously import exception names and a bunch of other stuff needed to use Obj. "from module import Obj, ObjException, ..." gets tiresome quickly.

    0 讨论(0)
  • 2020-12-29 10:23

    Class attributes are often used to allow overriding defaults in subclasses. For example, BaseHTTPRequestHandler has class constants sys_version and server_version, the latter defaulting to "BaseHTTP/" + __version__. SimpleHTTPRequestHandler overrides server_version to "SimpleHTTP/" + __version__.

    0 讨论(0)
  • 2020-12-29 10:27

    what is a good use case for class attributes

    Case 0. Class methods are just class attributes. This is not just a technical similarity - you can access and modify class methods at runtime by assigning callables to them.

    Case 1. A module can easily define several classes. It's reasonable to encapsulate everything about class A into A... and everything about class B into B.... For example,

    # module xxx
    class X:
        MAX_THREADS = 100
        ...
    
    # main program
    from xxx import X
    
    if nthreads < X.MAX_THREADS: ...
    

    Case 2. This class has lots of default attributes which can be modified in an instance. Here the ability to leave attribute to be a 'global default' is a feature, not bug.

    class NiceDiff:
        """Formats time difference given in seconds into a form '15 minutes ago'."""
    
        magic = .249
        pattern = 'in {0}', 'right now', '{0} ago'
    
        divisions = 1
    
        # there are more default attributes
    

    One creates instance of NiceDiff to use the existing or slightly modified formatting, but a localizer to a different language subclasses the class to implement some functions in a fundamentally different way and redefine constants:

    class Разница(NiceDiff): # NiceDiff localized to Russian
        '''Из разницы во времени, типа -300, делает конкретно '5 минут назад'.'''
    
        pattern = 'через {0}', 'прям щас', '{0} назад'
    

    Your cases:

    • constants -- yes, I put them to class. It's strange to say self.CONSTANT = ..., so I don't see a big risk for clobbering them.
    • Default attribute -- mixed, as above may go to class, but may also go to __init__ depending on the semantics.
    • Global data structure --- goes to class if used only by the class, but may also go to module, in either case must be very well-documented.
    0 讨论(0)
  • 2020-12-29 10:37

    Encapsulation is a good principle: when an attribute is inside the class it pertains to instead of being in the global scope, this gives additional information to people reading the code.

    In your situations 1-4, I would thus avoid globals as much as I can, and prefer using class attributes, which allow one to benefit from encapsulation.

    0 讨论(0)
提交回复
热议问题