我对Python super()以及继承和属性有一个非常奇怪的问题.一,代码:
#!/usr/bin/env python3
import pyglet
import pygame
class Sprite(pyglet.sprite.Sprite):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.x, self.y
@property
def x(self):
return super().x
@x.setter
def x(self, value):
super(Sprite, self.__class__).x.fset(self, value)
self.rect.centerx = value
@property
def y(self):
return super().y
@y.setter
def y(self, value):
super(Sprite, self.__class__).y.fset(self, value)
self.rect.centery = value
Run Code Online (Sandbox Code Playgroud)
这很好用.但是,我想要什么(对我来说似乎是Pythonic)
#super(Sprite, self.__class__).x.fset(self, value)
super().x = value
Run Code Online (Sandbox Code Playgroud)
虽然不起作用
super().x
Run Code Online (Sandbox Code Playgroud)
得到的价值很好.在这种情况下,x是超类的属性,同时定义了fset和fget.那为什么不起作用呢?
Pyflakes与以下代码的处理不太合理:
@property
def nodes(self):
return self._nodes
@nodes.setter
def nodes(self, nodes):
"""
set the nodes on this object.
"""
assert nodes != [] # without nodes no route..
self.node_names = [node.name for node in nodes]
self._nodes = nodes
Run Code Online (Sandbox Code Playgroud)
使用使用pyflakes的vim和syntastic我得到以下错误:
W806 redefinition of function 'nodes' from line 5
Run Code Online (Sandbox Code Playgroud)
所以我收到警告,@nodes.setter因为我重新定义了nodes.
如何禁用此无用警告,因为此代码是正确的?或者哪个python检查器正确处理此代码?
更新
我在重构代码时遇到了一些问题,因为属性和函数具有不同的继承行为.访问基类的属性是不同的.看到:
所以我现在倾向于避免使用这种语法并使用适当的函数.
你怎么能扩展python属性?
子类可以通过在重载版本中调用它来扩展超类的函数,然后对结果进行操作.这是我说"扩展函数"时的一个例子:
# Extending a function (a tongue-in-cheek example)
class NormalMath(object):
def __init__(self, number):
self.number = number
def add_pi(self):
n = self.number
return n + 3.1415
class NewMath(object):
def add_pi(self):
# NewMath doesn't know how NormalMath added pi (and shouldn't need to).
# It just uses the result.
n = NormalMath.add_pi(self)
# In NewMath, fractions are considered too hard for our users.
# We therefore silently convert them to integers.
return int(n)
Run Code Online (Sandbox Code Playgroud)
是否有类似于扩展函数的操作,但对于使用属性装饰器的函数?
我想在获得昂贵的计算属性后立即进行一些额外的计算.我需要保持属性的访问权限.我不希望用户必须调用特殊例程来进行计算.基本上,我不希望用户知道首先进行的计算.但是,该属性必须保留属性,因为我需要支持遗留代码.
也许这是装饰师的工作?如果我没有弄错,decorator是一个包装另一个函数的函数,我想用一些更多的计算来包装一个属性,然后再将它作为一个属性呈现,这看起来像一个类似的想法......但是我无法弄明白.
我有一个基类LogFile,它具有昂贵的构造属性 …
这个问题类似于另一个问题,区别在于基类中的数据成员没有被描述符协议包装.
换句话说,如果我使用派生类中的属性覆盖其名称,我该如何访问基类的成员?
class Base(object):
def __init__(self):
self.foo = 5
class Derived(Base):
def __init__(self):
Base.__init__(self)
@property
def foo(self):
return 1 + self.foo # doesn't work of course!
@foo.setter
def foo(self, f):
self._foo = f
bar = Base()
print bar.foo
foobar = Derived()
print foobar.foo
Run Code Online (Sandbox Code Playgroud)
请注意,我还需要定义一个setter,否则在基类中分配self.foo不起作用.
总而言之,描述符协议似乎与继承没有很好的交互...
我正在使用 South 在 Django 中进行架构和数据迁移。我有一个这样的模型:
class ModelFoo(models.Model):
first_name = models.CharField()
last_name = models.CharField()
@property
def full_name(self):
return self.first_name + self.last_name
Run Code Online (Sandbox Code Playgroud)
而在south数据迁移代码中,我想直接使用full_name,如下所示:
foo.full_name
Run Code Online (Sandbox Code Playgroud)
但我收到一个错误:
AttributeError: 'ModelFoo' object has no attribute 'full_name'
Run Code Online (Sandbox Code Playgroud)
这里出了什么问题?我确信在 Django 的视图代码中使用 'full_name' 是可以的,为什么这里失败呢?
python ×5
inheritance ×2
properties ×2
decorator ×1
descriptor ×1
django ×1
django-south ×1
extends ×1
overloading ×1
pyflakes ×1
super ×1