【问题标题】:How to use a function outside a class as a property inside a class?如何将类外的函数用作类内的属性?
【发布时间】:2019-08-28 10:20:45
【问题描述】:

我遇到了一些问题。我们如何在可以在类属性中使用的函数之外定义一个函数?另外,我们如何将self 参数插入到函数签名中?我想把它想象成这样:

>>> def a(self, x):   #I thought maybe class will give "self" to this property function
...     print(self)
... 
>>> class aa:
...     def __init__(self):
...         pass
...     @a
...     def p():
...         print('in it')
... 
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in aa
    TypeError: a() missing 1 required positional argument: 'x'

我想在外部定义一个函数,但在类内部使用。就像一个类的方法作为一个属性。我该怎么做?

【问题讨论】:

  • 我不确定我是否理解您的要求。每当aa 实例的某些属性被访问时,您是否要实际使用property 调用a 函数?或者你只是使用property 作为装饰器的一个例子,它经常与@property 一起应用?因为你可以做这些事情中的任何一个,如果你明白你想要什么。您也可以将定义在类之外的函数复制到类中,并将其用作常规方法(不涉及装饰器或属性)!
  • 第一个。我要获取类的属性

标签: python python-3.x abc


【解决方案1】:

目前还不清楚你想让你的课外函数做什么。有很多可能性,但您可能还不知道向我们描述它的术语。

以下是我认为最有可能的三个:

  1. 你可能希望你的函数是一个装饰器。这意味着您可以将它应用到具有@decorator 语法的方法到其他函数,包括类中的方法。

    为此,您的函数需要编写为接受一个函数对象作为其唯一参数。无论它返回什么都会替换它被调用的函数或方法,所以通常你想返回一个可调用的,但你可以返回一个像property 这样的描述符。试试这样的:

    def decorator(func):
        def wrapper(self, *args, **kwargs):
            print("in the wrapper")
            result = func(self, *args, **kwargs)
            print("wrapper is done")
            return result
        return wrapper
    
    class Foo:
        @decorator
        def foo(self, x):
            print("in foo(), x is", x)
    
    f = Foo()
    f.foo(1) # prints three messages
    

    当您调用foo 方法时,您实际上将调用装饰器在将其应用于原始方法(func) 后返回的wrapper 方法。由于我们编写包装器的方式,它会调用func,因此原始方法也会打印出它的消息。

  2. 您可能希望使用property描述符 类型)来调用您的类外函数。这是使用property 的一种不太常见的方式,而不是将其用作方法上的装饰器,但这并非不可能。您甚至可以有两个不同的函数,一个在请求属性时调用,另一个在设置它时调用(但我将仅使用 getter 进行演示):

    def getter(obj):
        print("in the getter")
        return 1
    
    class Foo2:
        foo = property(getter)
    
    f2 = Foo2()
    print(f2.foo) # prints a message from the getter function first, then prints 1
    

    请注意,以这种方式构建属性时,您不能使用@decorator 语法。这只是紧接在函数定义之前的合法语法,我们没有在类中以这种方式定义任何函数。

  3. 您可能只想将定义在类之外的函数复制到其中,而不需要任何装饰器或属性废话。这是最简单的,只是一个简单的任务:

    def func(self, x):
        print("x is", x)
    
    class Foo3:
        method = func  # just assign the global to a name in the class body
        func = func    # you can even use the same name if you don't mind confusing people
    
    f3 = Foo3()
    f3.method(1)
    f3.func(2)
    

【讨论】:

    【解决方案2】:

    如果你想创建一个使用在你的类之外定义的函数的属性,它应该是这样的:

    def myfunc(self):
        return self._p
    
    class Foo:
        def __init__(self, p):
            self._p = p
        p = property(myfunc)
    
    f = Foo("Alpha")
    f.p # gives "Alpha"
    

    property 接受一个函数作为其(第一个)参数。该函数应将self 作为参数,并应返回您希望属性评估为的值。

    【讨论】:

    • property created.but 当我尝试像 @p 一样使用它时,它给出的属性是不可调用的..
    • @Günel 你为什么要放@p
    • 本质上的问题是我想在外面定义一个函数,我想在类中使用它作为“将采用方法(类中的函数)”并返回任何东西的属性。在这个函数中,我也想和自己一起工作。
    • 您使用“属性”这个词来表示属性以外的东西,这很不清楚。
    • 是的,我已经说过了。也许不是属性,而是像属性一样。我会用“@”语句来使用它。将采用类和自我的方法……先生清楚吗?跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 2021-11-27
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    相关资源
    最近更新 更多