如何在Python中调用__init__后立即调用特定的某个函数?

发布于 2025-01-10 10:09:08 字数 2035 浏览 5 评论 0原文

这是一个示例类Permit

class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]

我想做的:

  • self.todo列表中注册一些新元素,但不影响原始的__init__函数
  • self.todo 必须在调用 __init__ 后立即修改(就像新的 __init__ 函数),
  • 例如,我想将新元素插入到self.todo 就像以下,但元素和插入位置不确定,并且由用户指定,
class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]
        
        # new elements
        self.todo.insert(6,3)

我知道在 __init__ 中添加函数参数可能会有所帮助,例如 def __init__(self, elements,locations):。不过,这个修改是instance级别的,当Permit类创建的实例很多时,就必须一一修改。

所以我想在class级别注册新元素,这意味着新元素可以在调用__init__函数后注册(就像修改原来的__init__)。

我想知道是否可以在某个函数中注册新元素,并确保在调用 __init__ 函数后立即调用它们。

PS:metaclass 有帮助吗?如何帮助?

#################################################### ########## 更新:抱歉我的语言不好,我将在下面更具体地描述我的要求: 我有:

  • 一个默认类(Permit)
class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]
        ... # deal with todo list

  • 一个默认配置文件
from yacs.config import CfgNode as CN
cfg = CN()
...

我想做的:

  • 支持用户添加插件方法,由额外配置文件和方法文件组成,例如: 额外的配置文件:
def add_cfg(cfg):
    cfg.method = CN()
    cfg.method.param1 = 1.

额外的功能文件和寄存器

new_element1=1
new_element2=2
registry = {"new_element1": {"class": Permit, "position":-1,}, "new_element2": {"class": Permit, "position":4,}}
  • 我不希望用户修改源代码,添加新的配置和方法文件作为插件就足够了。
  • Permit 已在我的库中调用,因此我不希望创建像 Permit2 这样的新子类

Here is an example class Permit:

class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]

What I wanna do:

  • register some new elements in self.todo list, but not affect the original __init__ function
  • self.todo must be modified right after __init__ is called (just like a new __init__ function)
  • for example, I want to insert new element into self.todo just like the following, but the element and insert location is uncertain and specified by users
class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]
        
        # new elements
        self.todo.insert(6,3)

I know adding function parameters in __init__ may help, like def __init__(self, elements, locations):. However, this modification is instance-level, when there are many instances created by Permit class, you have to modified them one by one.

So I want to register new elements in class-level, which means the new elements can be registered after calling __init__ function (just like modifying the original __init__).

I wonder if I can register new elements in some certain function and make sure they are called right after calling __init__ function.

PS: Does metaclass help and how?

############################################################
Update: sorry for my poor language, I will describe my requirement more specific in the following:
I have:

  • a default class (Permit)
class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]
        ... # deal with todo list

  • a default config file
from yacs.config import CfgNode as CN
cfg = CN()
...

what I wanna do:

  • support user to add plugin methods, consisted by extra config file and method file like:
    extra config file:
def add_cfg(cfg):
    cfg.method = CN()
    cfg.method.param1 = 1.

extra function file and a registery

new_element1=1
new_element2=2
registry = {"new_element1": {"class": Permit, "position":-1,}, "new_element2": {"class": Permit, "position":4,}}
  • I don't want the users to modify source code, adding new configs and method file as plugin is enough.
  • Permit is already called in the my library, so I wish not to create a new child class like Permit2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绳情 2025-01-17 10:09:08

您可以在 Python 中添加其他“构造函数”,方法是使用类方法实例化该类的实例并对该实例执行修改

class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]

    @classmethod
    def with_mod(cls, position, value):
        obj = cls()
        obj.todo.insert(position, value)
        return obj


foo = Permit()  # Instance with the default todo list
bar = Permit.with_mod(6, 3) # Instance where the todo list is then modified

You can add additional "constructors" in Python by using class methods that instantiate an instance of the class and perform modifications to that instance

class Permit(object):
    def __init__(self):
        super(Permit, self).__init__()
        # init todo list
        self.todo = [1,2,3,4,5]

    @classmethod
    def with_mod(cls, position, value):
        obj = cls()
        obj.todo.insert(position, value)
        return obj


foo = Permit()  # Instance with the default todo list
bar = Permit.with_mod(6, 3) # Instance where the todo list is then modified
平安喜乐 2025-01-17 10:09:08

我认为我不太明白您需要什么 - 但一方面,如果您可以将自定义元类附加到您的 Permit 类,则元类可以提供帮助:

元类' __call__方法负责创建类的新实例:它将在类上调用 __new__,返回一个新的、统一的实例,然后调用 __init__ 并将其传递给它实例__new__ 返回,并再次返回该实例(忽略 __init__ 的返回值)。

如果您希望在 __init__ 之后运行某些内容,只需将此逻辑添加到自定义元类call`:

class PostInit(type):  # deriving from type is what makes a metaclass
   def __call__(cls, *args, **kw):
       instance = super().__call__(*args, **kw) # "instance" now contains the new instance, after __init__ is run
       
       # code to retrieve custom configurations and apply to the instance:
       ...
       return instance


class Permit(metaclass=PostInit):
    ...

I don't think I quite understood what you need - but for one thing metaclasses can help, if you can attach a custom metaclass to your Permit class:

The metaclass ' __call__ method is what is responsible for creating a new instance of a class: it will call __new__ on the class, which returns a new, unitialized instance, then call __init__ passing it the instance __new__ returned, and return that instance again (disregaring the return value of __init__).

If you want something to run after __init__, just add this logic to a custom metaclasscall`:

class PostInit(type):  # deriving from type is what makes a metaclass
   def __call__(cls, *args, **kw):
       instance = super().__call__(*args, **kw) # "instance" now contains the new instance, after __init__ is run
       
       # code to retrieve custom configurations and apply to the instance:
       ...
       return instance


class Permit(metaclass=PostInit):
    ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文