我目前正在使用Pygame中的一个小型RPG来习惯面向对象的编码。
在研究如何自动更新属性时,我遇到了以下内容:
class P:
def __init__(self,x):
self.x = x
@property
def x(self):
return self.__x
@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x
我尝试将其应用于我的代码,但是我收到以下错误:
File "weapons.py", line 13, in __init__
self.name = '{} {}'.format(ammo, self.raw_name)
TypeError: name() takes exactly 3 arguments (2 given)
我理解错误是什么,但我不知道如何解决它,因为我需要raw_name和ammo属性来自动更新我的Arrow实例的名称。
我的班级是这样的:
class Projectile(Item):
def __init__(self, name, value, image, x, y, speed, dmg, dmg_modif, ammo):
super(Projectile, self).__init__(name, value, image, x, y)
self.dest = (self.rect[0],self.rect[1])
self.speed = speed
self.dmg_modif = dmg_modif
self.dmg = dmg
self.orientation = 0
self.ammo = ammo
@property
def name(self):
return self.___name
@name.setter
def name(self, raw_name, ammo):
if '{} {}'.format(raw_name,ammo) != self.___name:
self.___name = '{} {}'.format(raw_name,ammo)
返回错误的子类是:
class Arrow(Projectile):
def __init__(self, ammo): #name, value, image, x, y, dmg
self.raw_name = 'Arrows'
self.name = '{} {}'.format(ammo, self.raw_name)
self.value = 5
self.image = variables.quiver_img
self.speed = 4
self.dmg = 2
self.dmg_modif = 1
super(Arrow, self).__init__(self.name, self.value, self.image, 200, 150, self.speed, self.dmg, self.dmg_modif, ammo)
父类是Item和MySprite:
class Item(MySprite):
def __init__(self, name, value, image, x, y):
# Call the parent class (Sprite) constructor
super(Item, self).__init__(image, x, y)
self.name = name
self.value = value
self.inv_pos = -1
和
class MySprite(pygame.sprite.Sprite):
def __init__(self,image,x,y):
# Call the parent class (Sprite) constructor
super(MySprite, self).__init__()
self.image = image
self.rect = self.image.get_rect().move(x, y) #initial placement
self.top_cp = (self.rect[0]+self.rect[2]/2,self.rect[1])
self.bot_cp = (self.top_cp[0],self.rect[1]+self.rect[3])
self.left_cp = (self.rect[0],self.rect[1]+self.rect[3]/2)
self.right_cp = (self.left_cp[0]+self.rect[2],self.left_cp[1])
self.center = self.rect.center
self.pos = self.rect.topleft
self.blit_order = 1
self.level = variables.current_level #Level(1)#level to which sprite belongs
欢迎任何帮助!
答案 0 :(得分:0)
下次请提供minimal example。
您的代码看起来有点复杂。好的,第一个问题是你不能将多个参数传递给setter。您既可以传递元组,也可以使用传统的setter方法def set_name(self, name, ammo):
。
另一个问题是您在设置之前使用___name
属性,例如在Arrow
s __init__
方法的第二行。
私有属性应该有一个下划线而不是三个(这只是一个警告其他程序员的惯例)。如果您有两个或更多下划线,则名称为mangled。
此外,我认为只有在新名称等于旧名称(有点无意义;))时才更改setter中的名称。你到底想要做什么?也许你根本不需要属性。
这是您的代码的固定(最小)版本:
import pygame
class MySprite(pygame.sprite.Sprite):
def __init__(self):
super(MySprite, self).__init__()
class Item(MySprite):
def __init__(self, name):
super(Item, self).__init__()
self.name = name
class Projectile(Item):
def __init__(self, name):
super(Projectile, self).__init__(name)
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name + ' foo'
class Arrow(Projectile):
def __init__(self):
super(Arrow, self).__init__(name='Arrows')
arrow = Arrow()
print(arrow.name)
arrow.name = 'New name'
print(arrow.name)
答案 1 :(得分:0)
所以我最终设法解决了我的问题:
class Projectile(object):
def __init__(self, raw_name, ammo):
self.raw_name = raw_name
self.name = self.raw_name
self.ammo = ammo
@property
def ammo(self):
return self._ammo
@ammo.setter
def ammo(self, ammo):
self.name = str(ammo) + self.raw_name
self._ammo = ammo
class Arrow(Projectile):
def __init__(self):
self.raw_name = ' Arrows'
self.name = self.raw_name
super(Arrow, self).__init__(self.raw_name, ammo
= 10)
arrow = Arrow()
print arrow.ammo
print arrow.name
arrow.ammo = 15
print arrow.ammo
print arrow.name
给出:
>>>10
>>>10 Arrows
>>>15
>>>15 Arrows