无法使用python中的abc模块和属性访问成员变量

alf*_*_80 -1 python properties abc

我编写了一个模拟abc模块和模块使用的代码properties.但是,似乎我无法访问widthheight变量.代码如下:

from abc import ABCMeta, abstractmethod

class Polygon:

__metaclass__ = ABCMeta

@abstractmethod
def compute_area(self): pass


def __init__(self):
    self.width = None
    self.height = None

@property
def width_prop(self):
    return self.width

@property
def height_prop(self):
    return self.height

@width_setter.setter
def width_setter(self, width):
    self.width = width

@height_setter.setter
def height_setter(self, height):
    self.height = height



class Triangle(Polygon):
    def compute_area(self):
        return 0.5 * width * height




if __name__ == "__main__":
    tri = Triangle()
    tri.height_setter(20)
    tri.width_setter(30)
    print "Area of the triangle = ", tri.compute_area()
Run Code Online (Sandbox Code Playgroud)

我获得的错误消息是NameError: name 'width_setter' is not defined.我的实施可能有什么问题?

编辑:

from abc import ABCMeta, abstractmethod

class Polygon:

__metaclass__ = ABCMeta

@abstractmethod
def compute_area(self): pass


def __init__(self):
    self.width = None
    self.height = None

@property
def width_prop(self):
    return self.width

@width_prop.setter
def width_setter(self, width):
    self.width = width

@property
def height_prop(self):
    return self.height

@height_prop.setter
def height_setter(self, height):
    self.height = height



class Triangle(Polygon):
    def compute_area(self):
        return 0.5 * self.width * self.height




if __name__ == "__main__":
    tri = Triangle()
    tri.height_prop = 20
    tri.width_prop = 30
    print "Area of the triangle = ", tri.compute_area()
Run Code Online (Sandbox Code Playgroud)

Ned*_*der 15

将Python编写为Python,而不是C++或Java:

class Polygon:
    def compute_area(self):             # if you need this at all...
        raise NotImplementedError()     # what does it do for you?

    def __init__(self):
        self.width = None
        self.height = None

class Triangle(Polygon):
    def compute_area(self):
        return 0.5 * self.width * self.height

if __name__ == "__main__":
    tri = Triangle()
    tri.height = 20
    tri.width = 30
    print "Area of the triangle = ", tri.compute_area()
Run Code Online (Sandbox Code Playgroud)

  • @voo关于文档的观点是有效的,但是当你收到错误时你错了.如果子类没有实现该方法,则只有在使用该方法时才会出错.唯一的区别是它是AttributeError还是NotImplementedError. (3认同)
  • 那些提供子类的人在定义时会得到错误,而不仅仅是某个人稍后调用`compute_area`(是的,python是动态的,但是我个人总是喜欢比以后更快地得到错误).此外,它是一种很好的方式来在代码本身中记录子类必须提供的方法,而不仅仅是以注释形式. (2认同)

bru*_*ers 6

"固定"(但完全是unpythonic)代码:

class Polygon(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def compute_area(self): 
        pass

    def __init__(self):
        self.width = None
        self.height = None

    @property
    def width_prop(self):
        return self.width

    @width_prop.setter
    def width_prop(self, width):
        self.width = width

    @property
    def height_prop(self):
        return self.height

   @height_prop.setter
   def height_prop(self, height):
    self.height = height


class Triangle(Polygon):
    def compute_area(self):
        return 0.5 * self.width_prop * self.height_prop

if __name__ == "__main__":
    tri = Triangle()
    tri.height_prop = 20
    tri.width_prop = 30
    print "Area of the triangle = ", tri.compute_area()
Run Code Online (Sandbox Code Playgroud)

现在是严肃的部分:Python不是Java.你不会对普通属性的访问,因为Python作为计算的属性相当不错的支持,需要getter/setter方法(该property类型你没有正确使用是一个非常简单普通的-但很方便-执行).你的getter和setter没有做任何有用的事情,你将获得直接访问属性的相同结果(代码更少,性能更好):

class Polygon(whatever):
    __metaclass__ = ABCMeta

    def __init__(self, witdh=None, height=None):
        self.width = width
        self.height = height


    @abstractmethod
    def compute_area(self): 
        pass


class Triangle(Polygon):
    def compute_area(self):
        return 0.5 * self.width * self.height


if __name__ == "__main__":
    tri = Triangle(20, 30)
    print "Area of the triangle = ", tri.compute_area()
Run Code Online (Sandbox Code Playgroud)

对于记录,Python没有"私有"/"公共"关键字 - 只有以前导下划线开头的名称是"实现内容",并且应该被客户端代码访问.请注意,"不应该"仅表示它的含义:没有什么可以阻止您访问它们,但是如果有任何中断,现在或在下一个版本中都不要抱怨.一种"保修无效,如果未密封".

wrt /正确使用或属性:我不会详细介绍(需要深入的Python执行模型和对象模型说明),但正确的语法是:

class MyClass(object):

    def __init__(self, prop):
        # this will invoke prop.setter
        self.prop = prop

    # defines a property named "prop"
    # will be accessed just like a plain
    # attribute but will go thru the getter and setter

    @property
    def prop(self):
        # this is the getter
        return self._some_val * 42

    # now add a setter to 'prop':
    @prop.setter
    def prop(self, val):
        self._some_val = val / 42


obj = MyClass(10)
print obj.prop
obj.prop = 5
print obj.prop
Run Code Online (Sandbox Code Playgroud)

另外(最后):Python没有"隐含此"(或"隐式自我").您必须self.attr在方法中使用才能访问任何属性.