【问题标题】:Is it possible in Python to make a set of methods of a class dependent on input of constructor?是否可以在 Python 中根据构造函数的输入创建一组类的方法?
【发布时间】:2013-07-22 05:27:16
【问题描述】:

我正在阅读此Genshi Tutorial 并查看以下示例:

from formencode import Schema, validators

class LinkForm(Schema):
    username = validators.UnicodeString(not_empty=True)
    url = validators.URL(not_empty=True, add_http=True, check_exists=False)
    title = validators.UnicodeString(not_empty=True)

据我了解这个例子,我们创建一个继承Schema类的新类,这个类包含三个方法:usernameurltitle。但是,我不确定最后一个,因为之前我只看到使用def 创建的方法。

无论如何,我的问题与此无关。我想知道是否可以使类的定义动态化。例如,有时我不希望urltitle 在课堂上。这似乎是可行的(我只使用if 并仅在满足语句的情况下为 url 分配一个值。

但是如果我事先不知道我想在表单中包含哪些字段怎么办?例如,现在我有用户名、网址和标题。但是,如果以后我想要cityage 怎么办。我可以这样做吗:

from formencode import Schema, validators

class LinkForm(Schema):

    __init__(self, fields):
          for field in fields:
               condition = fields[field]
               field = validators.UnicodeString(condition)

我认为这行不通。在这种情况下有解决办法吗?

【问题讨论】:

    标签: python class oop methods


    【解决方案1】:

    是的,您可以动态地向实例添加方法。不,你不能为所欲为。

    您可以将方法绑定到初始化程序中的实例。不幸的是,你所拥有的是descriptors,而那些必须绑定到类。

    【讨论】:

    • 好的。这可能意味着必须固定描述符的数量和名称。但是我至少可以操纵赋值运算符的右侧。换句话说,假设我总是有field_1 描述符,但分配给它的内容取决于构造函数的参数。有可能吗?
    • 我个人认为实例初始化程序不应该对类产生太大影响。我的意思是,它可以,但它可能不应该
    【解决方案2】:

    我会反过来——首先定义所有可能使用的表单字段,然后删除不需要的。

    前提是你有:

    from formencode import Schema, validators
    
    class LinkForm(Schema):
        username = validators.UnicodeString(not_empty=True)
        url = validators.URL(not_empty=True, add_http=True, check_exists=False)
        title = validators.UnicodeString(not_empty=True)
    

    你可以这样做:

    def xy():
        my_form = LinkForm()
        del my_form.url
        …
    

    ……或者这个:

    def xy():
        class CustomLinkForm(LinkForm):
            pass
        if …:
            del CustomLinkForm.url
        …
    

    免责声明:我对 FormEncode 不熟悉,因此这可能取决于它的内部工作原理,这两个版本中的哪一个真正有效。

    【讨论】:

    • 问题是我想要一个通用的代码。这意味着我事先不知道表单中可能包含哪些字段。因此,可能有数百万个潜在名称。
    【解决方案3】:

    当然你可以在self之后有一个带有一些参数的构造函数,如果你有这些参数,这些参数将是你的类的一些成员的值

    __init__(self, fields):
              self.fields = []
              for field in fields:
                   self.fields = self.fields + field 
    

    Dive into Python看到这个

    class FileInfo(UserDict):
        "store file metadata"               
        def __init__(self, filename=None): 
             UserDict.__init__(self)      
             self["name"] = filename 
    
    1. 类也可以(并且应该)有文档字符串,就像模块和 功能。

    2. init 在 类被创建。将其称为 类的构造函数。这很诱人,因为它看起来像 构造函数(按照惯例,init 是为 类),行为就像一个(它是在 新创建的类实例),甚至听起来像一个(“init” 当然暗示了一种构造函数的性质)。不正确,因为 在调用 init 时对象已经被构造, 并且您已经拥有对新实例的有效引用 班级。但是 init 是你最接近 Python 中的构造函数,它扮演的角色大致相同。

    3. 第一个 每个类方法的参数,包括 init,总是 引用类的当前实例。按照惯例,这 参数始终命名为 self。在 init 方法中,self 指的是 新创建的对象;在其他类方法中,它指的是 调用其方法的实例。虽然你需要指定 self 明确定义方法时,不指定 调用方法; Python 会自动为你添加。

    4. init 方法可以接受任意数量的参数,就像 函数,参数可以用默认值定义,使得 它们对调用者是可选的。在这种情况下,文件名有一个默认值 None 的值,即 Python 的空值。

    请注意,在后面的示例中,您将学习如何处理继承类,为此继承类调用__init()__

    要回答您关于类或实例变量的非问题,see this

    类定义中定义的变量是类变量;他们 由所有实例共享。要创建实例变量,它们可以是 在 self.name = value 的方法中设置。类和实例 变量可以通过符号“self.name”访问,并且 实例变量隐藏同名的类变量时 以这种方式访问​​。类变量可以用作默认值 实例变量,但使用可变值可能会导致 意想不到的结果。对于新式类,描述符可用于 创建具有不同实现细节的实例变量。

    【讨论】:

      猜你喜欢
      • 2021-04-25
      • 1970-01-01
      • 2020-03-08
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 2012-02-24
      • 1970-01-01
      • 2020-08-08
      相关资源
      最近更新 更多