Как использовать функцию вне класса как свойство внутри класса? - PullRequest
0 голосов
/ 07 апреля 2019

У меня проблемы. Как мы можем определить функцию вне функции, которая может быть использована в свойстве класса? Кроме того, как мы можем вставить параметр 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'

Я хочу определить функцию снаружи, но использовать внутри класса. Как метод класса как свойство. Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Не совсем понятно, что вы хотите, чтобы выполнялась ваша внеклассная функция. Существует множество возможностей, но вы, возможно, еще не знаете терминологию, чтобы описать ее нам.

Вот три, которые, я думаю, наиболее вероятны:

  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, вы на самом деле будете вызывать метод wrapper, который возвратил декоратор после его применения к исходному методу (func). Из-за того, как мы написали оболочку, она будет вызывать func, поэтому оригинальный метод также печатает свое сообщение.

  2. Вы можете использовать property (дескриптор типа ) для вызова вашей внеклассной функции. Это менее распространенный способ использования property, чем применение его в качестве декоратора для метода, но это не невозможно. Вы могли бы даже иметь две разные функции, одна из которых будет вызываться при запросе атрибута, а другая - не при вызове при его установке (но я продемонстрирую только с помощью метода получения):

    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)
    
0 голосов
/ 07 апреля 2019

Если вы хотите создать свойство, которое использует функцию, определенную вне вашего класса, это будет примерно так:

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 в качестве параметра и должна возвращать значение, для которого нужно оценить свойство.

...