In python, any way to automatically run functions as soon as a class is defined?

核能气质少年 提交于 2021-01-28 02:21:01

问题


I am developing a class. The class-level data it will need is going to be relatively complex. To save typing and minimize mistakes, I would like to define a good bit of this data through functions. Also, I would like to make this data available to the user even if they aren't ready to instantiate the class. So, I wonder, is there a way to get these functions to run automatically as soon as the class is defined? As an example, I want something like

import numpy as np    

def class foo:

        @this_should_run_before_instantiation
        def define_bar:
            bar = np.range(100)

       @this_should_also_run_before_init
       def define_something_really complicated:
            bleh = # something that is too complicated for a single line or lambda

        def __init__(self):
            # etc.

So then the user can do something like

>>>from foopackage import foo
>>>foo.bar
array([ 0,  1,  2,  3,  4,  5,  ... #etc.
>>>foo.bleh
< whatever bleh is ... >

回答1:


The sane / simple way to handle this is for you the author of the class to do this explicitely. So something like:

class Foo:
    @classmethod # don't have to be but will likely benefit from being classmethods...
    def _define_something_really_complicated(cls):
        ...
    @classmethod
    def _define_something_else_really_complicated(cls):
        ...
    @classmethod
    def _build(cls):
        cls._define_something_really_complicated()
        cls._define_something_else_really_complicated()
        ...
    def __init__(self):
        ...

Foo._build() # where your module is defined.

Then whenever a consumer does import foo; my_foo_instance = foo.Foo() it will already be built.

You could create a metaclass which inspects the class members for some tag and it will automatically do this, but honestly, the above makes everything very clear to me and to future readers of your class (best not to move initialization of variables into magical-seeming metaclass foo).




回答2:


Class attributes are initialized when the class is defined. No function is needed.

import numpy as np    

class Foo:
    bar = np.range(100)
    def __init__(self):
        # etc.

If you want a function that you can call after import but before instantiating the class at all, you can define a class function.

class Foo:
    @classmethod
    def initialize_bar(cls):
        cls.bar = np.range(100)

Then...

>>> from foopackage import Foo
>>> Foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute 'bar'
>>> Foo.initialize_bar()
>>> Foo.bar
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
       34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
       51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
       68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
       85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])



回答3:


You could try:

#file Foo.py

import numpy as np

bar = np.range(100)

class foo:
    pass

Then

# file main.py
import Foo

b = Foo.bar
foo_instance = Foo.foo()



回答4:


Whatever code you include on the top level of the module will be executed at import time.

Normally it's just function and class declarations. But you can put any code at the top level:

# module1.py
def foo():
  return bar

A = 100
print('You just imported module1')

Then you can import module1 and see the message printed, and foo.A to equal 100.

Executing code with side effects at import time is usually not the most brilliant idea; make sure you understand what you are doing, and why. (Otherwise, don't do it, and provide an initialization function.)




回答5:


Maybe this (variant 1)

def complex_data_calc():
    return range(42)

class Foo:
    bar = compex_data_calc()

    def __init__(self):
        pass

or this (variant 2)

class Foo:
    @staticmethod
    def bar():
        return range(42)

    def __init__(self):
        pass

and call with

from foopackage import Foo
Foo.bar    # variant 1
Foo.bar()  # variant 2


来源:https://stackoverflow.com/questions/59724810/in-python-any-way-to-automatically-run-functions-as-soon-as-a-class-is-defined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!