简体   繁体   中英

instantiate python object immediately after its class definition

In a large python project (openerp) I encounter several times the following pattern:

In a module, a class with its methods is defined. Then, in the same module and immediately after the class definition, an instance of the class is instantiated, that is then called from other modules.

# in module_A.py:
class ClassA(object):

    def __init__(self, default="Hello world!"):
        self.default = default 

    def my_method(self, data):
        print self.default
        print data

object_a = ClassA()

To me it looks simpler to define the methods as module functions, without the class lookup overload:

# in module_B.py:

default = "Hello world!"

def my_method(data):
    print default
    print data

Seen from other modules, the usage is very similar:

from module_a import object_a as prefix
prefix.my_method("I'm so objective!")

versus:

import module_b as prefix
prefix.my_method("I'm so modular!")

Is there any rationale to prefer pattern A over pattern B? Or is pattern B more pythonic?

Sometimes, you want different clients to be able to use your module with different settings in such a way that they don't conflict with each other. For example, Python's random module provides a bunch of random number generation functions that are actually bound methods of a hidden Random instance. Most users don't care too much what algorithm generates their random numbers or whether other modules asking for random numbers will change the sequence. However, users who do care can get their own Random object and generate sequences of random numbers that won't be affected by other modules asking for random numbers.

Sometimes, something that's global now might not always be global. For example, if you're working on a planetary-scale RTS, you might have a Planet class with one instance, because the battle only happens on one planet. However, you don't want to rule out the possibility of building something like Planetary Annihilation, with battles stretching across entire solar systems and dropping extinction-event asteroids as superweapons. If you get rid of the Planet class and make its methods and attributes module-level, it'll be much harder to go back and add more planets later.

Sometimes, it's more readable to have objects doing things instead of modules. For example, suppose module joebob defines two objects evil_overlord_bob and good_guy_joe .

class Bob(object):
    def slaughter_everything(self):
        print "Muahahaha! Die for my amusement!"
class Joe(object):
    def stop_bob(self):
        print "I won't let you hurt those innocents!"
evil_overlord_bob = Bob()
good_guy_joe = Joe()

Suppose Bob and Joe are very unique people. It's unthinkable that you'd want to create another object anything like Bob or Joe. In that case, you could move slaughter_everything and stop_bob to module-level and get rid of the Bob and Joe classes and objects entirely. However, then you'd be writing

joebob.slaughter_everything()
joebob.stop_bob()

It's much clearer what's going on if you can say

evil_overlord_bob.slaughter_everything()
good_guy_joe.stop_bob()

even if you'll never need to instantiate Bob's equally-evil twin brother greg_the_fleshripper .

Among other benefits, using classes allows you to use the introspection on the instances, which is something you cannot do with functions.

In a more general way, both approaches are "pythonic". Use one of the other really depends on the type of project (small/big, with/without GUI, ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM