没有父类的名称,请参阅parent的类方法

时间:2017-02-21 04:06:13

标签: python python-decorators class-method

我希望你做得很好。这个问题实际上是关于摆脱对基类的引用。

基本上我想使用父类方法在类级别而不是实例级别收集子类方法的所有方法。但是,我被告知基类名称真的很长。

第一件作品有效,但因为名字很长而真的很烦人。即使在干净的版本中,我每次都必须做A.eat。

我保证人们不会在像B这样的孩子中定义另一种方法“吃”。我能否真正摆脱基类引用以便我可以使用@eat?

 <article>
    <figure class="fig">
        <img src="parks/arches.jpg" alt="Arches" />
        <figcaption>
        Arches National Park
        </figcaption>
    </figure>   
    <figure class="fig">
    <img src="parks/glacier.jpg" alt="Glacier" />
    <figcaption>
    Glacier National Park
    </figcaption>
    </figure>

    <figure class="fig">
    <img src="parks/teton.jpg" alt="Teton" />
    <figcaption>Grand Teton National Park</figcaption>
    </figure>

    <figure class="fig">
    <img src="parks/yellowstone.jpg" alt="Yellowstone" />
    <figcaption>Yellowstone National Park</figcaption>
    </figure>

    <figure class="fig">
    <img src="parks/yosemite.jpg" alt="Yosemite" />
    <figcaption>Yosemite National Park</figcaption>
    </figure>

    <figure class="fig">
    <img src="parks/zion.jpg" alt="Zion" />
    <figcaption>Zion National Park</figcaption>
    </figure>

    </article>
  </section>

清洁版:

class IDontWantToDoThisButNameHasToBeThisLong(object):

  a = []

  @classmethod
  def eat(cls, func):
    cls.a.append(func)


class B(IDontWantToDoThisButNameHasToBeThisLong):

  @IDontWantToDoThisButNameHasToBeThisLong.eat
  def apple( self, x ):
    print x

  IDontWantToDoThisButNameHasToBeThisLong.eat( lambda x: x+1 )

x = B()

IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)

print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)

此致

2 个答案:

答案 0 :(得分:0)

班级IDontWantToDoThisButNameHasToBeThisLong实际上只是一个对象。在python中,大多数东西都是一个对象,所以我们可以为变量分配任何东西,包括一个类。

你在这里可以做的事情如下:

class IDontWantToDoThisButNameHasToBeThisLong(object):

    a = []

    @classmethod
    def eat(cls, func):
        cls.a.append(func)

A = IDontWantToDoThisButNameHasToBeThisLong


class B(A):

    @A.eat
    def apple( self, x ):
        print x

    A.eat( lambda x: x+1 )

x = B()

IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)        
A.a[0](x, 1)

print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)

答案 1 :(得分:0)

对于你想做的事情,没有完美的解决方案,但有一些不同的方法可能已经足够好了。

从最简单的开始,您可以在子类中使用类方法之前为长类提供更短的名称:

class IDontWantToDoThisButNameHasToBeThisLong(object):
    ...

A = IDontWantToDoThisButNameHasToBeThisLong

# later code can use A.whatever()

另一种选择是使用长名称将装饰器移出类,以便后面的代码直接将其称为全局方法,而不是类方法。这将需要稍微重新设计(如果你打算有多个不同的a列表通过不同的类调用的同一个装饰器访问,这可能会破坏事情):

class IDontWantToDoThisButNameHasToBeThisLong(object):
    a = []

def eat(func):
    IDontWantToDoThisButNameHasToBeThisLong.a.append(func) # only need to use the name once
    return func  # I suspect you want this too (a decorator should return a callable)

# later code can use @eat as a decorator, without referring to the long class name

这两种方法的混合可能是保持现有的类方法定义不变,但要为更容易访问的绑定方法创建另一个全局名称:

eat = IDontWantToDoThisButNameHasToBeThisLong.eat

最后一种可能的方法是对元类使用更高级的编程,或者(如果您使用的是Python 3.6)__init_subclass__或类似的方法,以实现您的目标,而无需使用类作为装饰者的方法。我不打算包含相应的代码,因为最好的方法可能取决于您的设计的详细信息,而不是您在示例中显示的内容。