在Python中,如何根据类方法的返回值初始化类属性? [英] In Python, how to initialize a class attribute from the return value of a class method?

查看:144
本文介绍了在Python中,如何根据类方法的返回值初始化类属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下我们有这样的课程:

Imagine we have this class:

class Custom:
    @classmethod
    def get_choices(cls):
        # use cls attributes to return a list

    mapping = {"key": ... }

我想将 get_choices()返回的值与 key 。应该使用什么代码代替占位符 ...

I would like to associate the value returned by get_choices() to key. What code should go instead of the placeholder ... ?

编辑:我想让问题与上下文无关(在我看来,这一要求足够普遍,但我可能会有所偏见)。正如评论中所建议的那样,我将提供更多细节,因为似乎我们共享最直接的代码的担忧:

I wanted to keep the question context-agnostic (it seemed to me that this requirement was common enough, but I could be biased). As was suggested in comments, I will give some more details, because it seems we share the concern of 'most straightforward code':

我正在开发Django应用程序,我想在其中使用它们将枚举的值与 Model 分开。在我看来,自然的解决方案是创建一个 enumeration.py 模块,然后我可以在其中为每个枚举定义一个 class (该类至少具有用于生成值集合的类方法)。这是示例中的 get_choices()

I am working on a Django application, where I want to keep enumeration of values separated of the Models using them. What seemed to me like a natural solution was to create an enumeration.py module, where I could then define a class for each enumeration (the class having at least a class method to generate the collection of values). This is the get_choices() in the example.

现在,由于业务逻辑的原因,我需要映射这些选择一个键。这种映射在逻辑上与枚举相关联,在将它们放在同一个类中时似乎是一个很好的结构(给予客户端代码统一且显式的访问,并以类名作为前缀)。

Now, because of business logic, I need to map those choices to a key. This mapping being logically coupled to the enumeration, it seemed like a good structure to keep them together, in the same class (giving client code uniform and explicit access, being prefixed by the class name).

推荐答案

您不能在类定义中执行此操作,因为尚未创建类对象。
在类定义之后,您肯定可以执行以下操作-

You cannot do it in class definition because class object has not been created yet. After the class definition, you could definitely do something like this -

Custom.mapping['key'] = Custom.get_choices()

尽管推荐的方法是使用元类。

Although the recommended way to do this would be to use a metaclass.

class CustomMetaClass(type):

      def __init__(cls, classname, bases, attrs):
          super(CustomMetaClass, cls).__init__(classname, bases, attrs)

          cls.mapping['key'] = cls.get_choices()

class Custom(metaclass = CustomMetaClass): # assuming you are using python 3

      mapping = {}

      @classmethod
      def get_choices(cls):
          # add your custom code here
          pass

话虽如此,这是面向对象的解决方案问题。您当然可以使用一些函数来生成选择,从而结束使用元类的需要。

With that said, that is an Object Oriented solution to the problem. you can ofcourse use some function to generate choices thus ending the need to use metaclass.

在那种情况下,我认为您应该按照自己的建议维护一个名为 choices.py的文件,并在映射中使用它们,而不要使用 get_choices 类方法。如果您只需要存储选择,则不必为每种模型不必要地创建类。只需使用字典和常量即可。

In that case, I think you should just maintain a file named 'choices.py' as you yourself suggested and use them in your mapping, instead of get_choices class method. You don't need to unnecessarily make classes for each model if all you want to do is store choices. Just use dicts and constants.

如果需要动态生成类(例如,从db中生成),则需要创建单独的模型来存储选择。

If your classes needs to be generated dynamically, say from db, then you need to create separate model for storing choices.

class CustomModelChoices(models.Model):

      model_name = models.StringField(db_field = 'mn')
      choices = models.DictField(db_field = 'ch')

class CustomModel(models.Model):

     _choice_generator = CustomModelChoices

     mapping = {
         'key': CustomModelChoices.objects.get(model_name = 'CustomModel').choices
     }

这只是一个原始设计,可能需要改进很多,但是在这些方面还是有一些。

This is just a raw design, might need to be improved a lot, but something on these lines.

这篇关于在Python中,如何根据类方法的返回值初始化类属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆