Python 方法使用实例中的关键字';s属性

Python 方法使用实例中的关键字';s属性,python,class,methods,attributes,keyword-argument,Python,Class,Methods,Attributes,Keyword Argument,完美但不可能的情况是: class example(object): def __init__(self,x,y): self.x = x self.y = y def foo(self, x = self.x, y = self.y): return x + y 它不起作用,因为自我没有定义。我做了很多研究,研究了装饰器、描述符、元类,几乎所有的东西。这个解决方案可能是最显而易见的,也是大家都知道的,但我找不到它。我可以管理两

完美但不可能的情况是:

class example(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def foo(self, x = self.x, y = self.y):
        return x + y
它不起作用,因为自我没有定义。我做了很多研究,研究了装饰器、描述符、元类,几乎所有的东西。这个解决方案可能是最显而易见的,也是大家都知道的,但我找不到它。我可以管理两种变通方法,如下所示:

def prep(argslist, argsprovided, attributes):
        argsout = []
        for name in argslist:
            if name in argsprovided:
                argsout.append(argsprovided[name])
            else:
                argsout.append(getattr(attributes,name))

        return argsout

class example(object):

    # I can create a default instance or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    # I can wrap a function to use the self argument       
    def wrapper(self):
        def foo(x = self.x, y = self.y, z = self.z, w = self.w):
            return x + y + z + w
        return foo

    # I can wrap 'joo' alongside with foo, and make 'wrapper' return a list    
    def joo(self, **kwargs):
        [x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
        return x + y + z + 2*w

    # I can use my custom 'prep' function to to the job
    def foo(self, **kwargs):
        [x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
        return x + y + z + w



# Creates a default instance and a custom one        
c = example()
d = example(2,2,2,2)

# I can use 'foo' with the instance's default values with both wrapping and 'prepping'
print(c.wrapper()())
print(d.wrapper()())
print(c.foo())
print(d.foo())

# I can use 'foo' with a mix of default values and provided values with both wrapping and 'prepping'
print(c.wrapper()(1,2,3))
print(d.wrapper()(1,2,3))
print(c.foo(y = 3,z = 4,w = 5))
print(d.foo(y = 3,z = 4,w = 5))
代码打印出来:

4
8
4
8
7
8
13
14

我有一个很大的类,有很多函数,每个类都需要“foo”的行为。我的准备方案太耗时了。在分析代码之后,我认为它只在prep中花费了12秒。做这件事的聪明且省时的方法是什么?我完全迷路了。

我不确定它是否有用,但是使用None作为默认值并使用子句来确定值怎么样。例如:

def foo(self, x=None, y=None):
    real_x = x if x != None else self.x
    real_y = y if y != None else self.y
    return real_x + real_y

我找到了六种做我想做的事的方法。分析代码后,结果是:

afoo     foo       noo1     noo2     wrap1     wrap2
6.730    28.507    3.98     4.097    10.256    3.468
6.407    28.659    4.096    3.924    9.783     3.529
6.277    28.450    3.946    3.889    10.265    3.685
6.531    30.287    3.964    4.149    10.077    3.674
正如您将在前面看到的,
noo1
noo2
wap2
在代码方面非常相似。传统的方法
afoo
没有那么有效。我的自定义方法
foo
非常糟糕,
wrap1
只是为了完整性而测试的

afoo.py
缺点是每个函数参数都需要额外的一行

class example(object):

    # I can create a default class or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    def afoo(self, x = None, y = None, z = None, w = None):
        x = x if x != None else self.x
        y = y if y != None else self.y
        z = z if z != None else self.z
        w = w if w != None else self.w
        return x + y + z + w


c = example(2,2,2,2)
for i in range(0, 10000000):
    c.afoo(1,2,3,4)
foo.py
这是一种较慢的方法

def prep(argslist, argsprovided, attributes):
        argsout = []
        for name in argslist:
            if name in argsprovided:
                argsout.append(argsprovided[name])
            else:
                argsout.append(getattr(attributes,name))

        return argsout

class example(object):

    # I can create a default class or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    def foo(self, **kwargs):
        [x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
        return x + y + z + w


c = example(2,2,2,2)
for i in range(0, 10000000):
    c.foo(x = 1,y = 2,z = 3,w = 4)
wrapper1.py
效率远远低于
wrapper2.py

class example(object):

    # I can create a default class or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    def wrapper(self):
        def foo(x = self.x, y = self.y, z = self.z, w = self.w):
            return x + y + z + w
        return foo


c = example(2,2,2,2)
for i in range(0, 10000000):
    c.wrapper()(1,2,3,4)
wrapper2.py

noo1.py

noo2.py


在测试这些代码时,我将
prep
功能包括在所有代码中,舒尔的基本结构相同,因此时差将来自循环。

它确实更快!这是一个很好的选择,但是我的一些函数会占用10个参数,所以它不是那么实用。包装器方法只是稍微慢一点。最好的方法是定义k=c.wrapper(),然后使用k()。
class example(object):

    # I can create a default class or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    def wrapper(self):
        def foo(x = self.x, y = self.y, z = self.z, w = self.w):
            return x + y + z + w
        return foo


c = example(2,2,2,2)
k = c.wrapper()
for i in range(0, 10000000):
    k(1,2,3,4)
class example(object):

    # I can create a default class or a custom one
    def __init__(self,U,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

        def noo(x = self.x, y = self.y, z = self.z, w = self.w):
            return x + y + z + w

        self.noo = noo

c = example(2,2,2,2)
for i in range(0, 10000000):
    c.noo(1,2,3,4)
class example(object):

    # I can create a default class or a custom one
    def __init__(self,x = 1,y = 1,z = 1,w = 1):

        self.x = x
        self.y = y
        self.z = z
        self.w = w

    def __call__(self):
        def noo(x = self.x, y = self.y, z = self.z, w = self.w):
            return x + y + z + w

        self.noo = noo


c = example(2,2,2,2)
c()
for i in range(0, 10000000):
    c.noo(1,2,3,4)