2016-11-18 108 views
0

我想创建一个多边形类,当给定用户输入的边和长度时,该类将返回区域和边界。但是,它并不需要我试图传入__init__方法的两个变量。边和长度必须是私密的,并且必须通过用户输入来接收。用户输入不传递给__init__

import math 

class Polygon: 
    use = (input("Enter in the sides and length of sides seperated by a comma")) 
    ans = use.split(",") 
    __numofSides = ans[0] 
    __sideLength = ans[1] 

    def __init__(self, __numofSides, __sideLength): 
     self.__numofSides = __numofSides 
     self.__sideLength = __sideLength 

    def get__numofSides(self): 
     self.__numofSides = ans[0] 
     return __numofSides 

    def get__sideLength(self): 
     self.__sideLength = ans[1] 
     return __sideLength 

    def perimeter(self, __numofSides,__sideLength): 
     peri = self. __numofSides * self.__sideLength 
     return peri 

    def area(self, __numofSides, __sideLength): 
     area = (((__sideLength **2) * __numofSides)/(tan(4) *(math.pi/__numofSides))) 
     return area 

    def __str___(self,): 
     print("Number of Sides: {}\n Length of Sides: {}\n" \ 
       "Perimeter is: {}\n Area is: {}".format(__numofSides,__sideLength,peri,area)) 

def main(): 
    p1 = Polygon() 
    p1.perimeter() 
    p1.area() 
    p1.__str__() 

main() 
+0

如果您打算发布Python代码,请确保您准确地重现您的缩进。严重缩减的Python代码是无稽之谈。 – khelwood

+0

不要使用两个下划线,它会使Python解释器破坏名称。 –

+2

*'边和长度必须是私人的“* - 那么Python可能不是您的语言,即使使用'__name_mangling'也是可以访问的。如果您希望它不可变,请考虑子类化'namedtuple'。想要受保护的属性,请使用'@ property'。 – jonrsharpe

回答

1

这里是你的代码(没有数学的考虑)的快速代码审查:

您可以从object继承(与Python的2兼容):

class Polygon(object): 

简化参数名称,请勿使用双下划线:

def __init__(self, sides, length): 
     self.sides = sides 
     self.length = length 

使用实例变量self.sidesself.length,删除参数:

def perimeter(self): 
     return self.sides * self.length 

通过math.tan()

def area(self): 
     return ((self.length ** 2) * self.sides)/(math.tan(4) * (math.pi/self.sides)) 

更换tan()在你main()功能:

(使用Python 2,使用raw_input代替input

use = input("Enter in the sides and length of sides separated by a comma: ") 
ans = use.split(",") 

字符串值转换到int

sides = int(ans[0]) 
length = int(ans[1]) 

p1 = Polygon(sides, length) 

使用print()功能打印结果

print(p1.perimeter()) 
print(p1.area()) 
2

你似乎有OOP是如何工作Python中的根本性的误解。当你实例化一个类时,__init__()方法被调用,通常分配给实例变量的参数,就像这样:

class Pet(object): 

    def __init__(self, sides): 
     self._name = name # argument stored in self._name 

然后在自己喜欢的任意方式来利用这些,你可以访问他们通过实例:

def get_name(self): 
    return self._name 

注意,所有这些方法确实是返回self._name返回给调用者。有使用decorators这种情况下一个常见的成语:

@property 
def name(self): 
    return self._name 

这样做的好处相比,get_name()是双重的。首先,你可以调用的方法没有括号,就好像它是一个实例变量:

my_pet = Pet('Rosita') 
print(my_pet.name) 

>> Rosita 

其次,如果用户以后试图用别的东西来覆盖它的Python会引发AttributeError:

my_pet = Pet('Rosita') 
my_pet.name = 'Maggie' 

>> Traceback (most recent call last): 
>> File "<stdin>", line 1, in <module> 
>> AttributeError: can't set attribute 

在问候你的__repr__方法,我认为你的意思是这样的:

def __repr__(self): 
    return "<Polygon sides={}; length={}; perimeter={}; area={}>".format(
     self.sides, self.side_length, self.perimeter, self.area) 

__repr__当你做print(my_polygon)被称为或str(my_polygon)所以它应该返回一个字符串。

最后,您可能已经注意到我已经用一个前导下划线命名实例变量而不是两个。如果你想让你的类的用户知道一个特定的实例变量是“私有的”,并且他们不应该混淆它,那么最好用一个下划线前缀它的名字。原因在于它允许您使用相同名称的处理器方法和实例变量,同时避免使用name mangling。带有两个主要下划线的名称已被破坏,因此通常不推荐使用。

考虑到所有这些帐户,这里是你的代码的改写:

import math 

class RegularPolygon(object): 

    def __init__(self, sides, side_length): 
     self._sides = sides 
     self._side_length = side_length 

    @property 
    def sides(self): 
     return self._sides 

    @property 
    def side_length(self): 
     return self._side_length 

    @property 
    def perimeter(self): 
     return self.sides * self.side_length 

    @property 
    def area(self): 
     return ((self.side_length**2 * self._sides) 
       /(4 * math.tan(math.pi/self.sides))) 

    def __repr__(self): 
     return "<Polygon sides={}; length={}; perimeter={}; area={}>".format(
      self.sides, self.side_length, self.perimeter, self.area) 


if __name__ == '__main__': 
    poly = RegularPolygon(5, 7) 
    print(poly) 
1

这是我怎么会这样写:

from collections import namedtuple 
from math import pi, tan 

class Polygon(namedtuple('Polygon', 'sides,length')): 

    PROMPT = 'Enter in the number and length of sides, separated by a comma' 

    @property 
    def perimeter(self): 
     return self.sides * self.length 

    @property 
    def area(self): 
     return (self.sides * (self.length ** 2))/(4 * tan(pi/self.sides)) 

    @classmethod 
    def from_input(cls): 
     return cls(*map(int, input(cls.PROMPT).split(','))) 

为什么?因为:

  • namedtuple继承使得实例不变的,所以你不能重新分配初始创建后sideslength,同时给你合理的平等的比较和__repr__格式免费:

    >>> square = Polygon(4, 1) 
    >>> square 
    Polygon(sides=4, length=1) 
    >>> square.sides = 5 
    Traceback (most recent call last): 
        File "python", line 1, in <module> 
    AttributeError: can't set attribute 
    
  • 使用@property意味着您可以再次以只读方式轻松访问计算属性:

    >>> square.area 
    1.0000000000000002 
    >>> square.perimeter 
    4 
    >>> square.area = 7 
    Traceback (most recent call last): 
        File "python", line 1, in <module> 
    AttributeError: can't set attribute 
    
  • 使用@classmethod保持逻辑的类,在那里它属于内产生从用户输入的对象:

    >>> hexagon = Polygon.from_input() 
    Enter in the number and length of sides, separated by a comma 6,2 
    >>> hexagon 
    Polygon(sides=6, length=2) 
    >>> hexagon.area 
    10.392304845413264 
    >>> hexagon.perimeter 
    12 
    

    在当前的实现中,您的输入运行一次当类被定义,而不是用户时实际上是想创建一个实例。

Note: I've assumed you're using Python 3.x - if not you should use raw_input . Also your classes should inherit from object , when you're not using e.g. namedtuple .

2

你的问题是,你不及格什么__init__,要创建一流水平的变量时,你这样做:

class Foo: 
    x = 42 
    y = input("Don't do this, this is bad") 

这将被调用一次每个程序*,所以如果这是你需要的东西,你将永远无法提供不同的值。 如果你想传递参数给一个函数,你这样做,当你创建类的实例:

class Polygon: 
    def __init__(self, num_of_sides, side_length): 
     self._num_of_sides = num_of_sides 
     self._side_length = side_length 

正如其他人所说,在Python私有变量不实际上交通不便,虽然有正如jonrsharpe指出他的答案那样,强制他们是不可变的。您也可以调查__slots__其他选项。

*Per import, which is usually once per program, but there are ways you can get around that, but that's even worse. Unless you're going for an obfuscated Python contest, don't do that.

相关问题