3

您能否在下面的课程中澄清一下周长变量。

我知道这self.vertices是针对特定实例的。由于perimeter没有用 定义self,这是否意味着它是一个类变量?那么它不是对所有实例都通用吗?

将周界编码为 不是正确的方法self.perimeter,因此它恰当地声明给每个实例吗?

此代码来自一本书。

多边形.py

import math
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def distance(self, p2):
        return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2)

class Polygon:
    def __init__(self):
        self.vertices = []
    def add_point(self, point):
        self.vertices.append((point))
    def perimeter(self):
        perimeter = 0
        points = self.vertices + [self.vertices[0]]
        for i in range(len(self.vertices)):
            perimeter += points[i].distance(points[i+1])
        return perimeter
>>> square = Polygon() 
>>> square.add_point(Point(1,1)) 
>>> square.add_point(Point(1,2)) 
>>> square.add_point(Point(2,2)) 
>>> square.add_point(Point(2,1)) 
>>> square.perimeter() 
4.0 

新型

import math
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def distance(self, p2):
        return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2)

class Polygon:
        def __init__(self):
            self.vertices = []
        def add_point(self, point):
            self.vertices.append((point))
        def perimetermethod(self):
            self.perimeter = 0
            points = self.vertices + [self.vertices[0]]
            for i in range(len(self.vertices)):
                self.perimeter += points[i].distance(points[i+1])
            return self.perimeter

if __name__=='__main__':
    p1 = Polygon()
    p1.add_point(Point(1,1))
    p1.add_point(Point(1,2))
    p1.add_point(Point(2,2))
    p1.add_point(Point(2,1))
    print(p1.perimetermethod())
4

3 回答 3

6

分配一个新变量some_name = ...总是在最里面的封闭范围内创建变量(除非globalnonlocal正在发挥作用,但它们在这里不相关)。为对象分配新的属性名称会在该对象上创建属性。

因此self.foo = 1分配一个foo在当前引用的对象上命名的属性self。按照惯例,名称self用作方法的第一个参数,该方法接收调用该方法的对象。所以“用 self 定义一个变量”并没有什么特别之处。这只是关于分配给现有对象的属性的普通规则。实例对象本身中存在的任何属性显然必须特定于该实例。

perimeter = 0在类的perimeter方法内部Polygon在最里面的封闭范围内创建一个变量。这就是perimeter方法,所以它创建了一个局部变量。局部变量仅在函数调用期间存在,因此它既不是类变量也不是实例变量。除了该特定方法的范围之外,您无法从任何地方访问它(并且它在每次调用时都有一个新的完全独立的值),因此它不能对所有实例都通用。但是您也不能在每个特定实例上访问它的不同值,因此它也不是实例变量。

如果您有perimeter = 0一个方法之外的类块本身,那么最里面的封闭范围将是类块。将创建一个“类变量”,它只是类对象的一个​​属性。如果一个属性在一个类上,那么显然它不能特定于任何实例,因为只有一个类但可以有任意数量的实例。顺便说一句,这正是类的__init__add_pointperimeter 方法的含义Polygon;它们在类块中被分配(使用def语句),因此它们成为类对象的属性。


概括:

  1. self.foo = 1正在分配给当前引用的对象的属性self(这通常是“当前实例”)
  2. foo = 1 在类块中正在创建正在定义的类的类属性
  3. foo = 1 在 def 块中正在创建正在定义的函数的局部变量

但你不应该真的那样记住它。它们只是以下特殊情况:

  1. 分配给一个带点的名称就像foo.bar.baz = 1是写入一个对象的属性
  2. 分配给一个简单的名称,例如foo = 1写入最内层封闭范围内的变量
于 2012-08-20T02:32:56.940 回答
2

不,这意味着它是本地的。此外,您不想使用,self.perimeter因为它会影响具有相同名称的方法。

于 2012-08-20T02:11:59.440 回答
0

在您的代码中,有两件事称为perimeter. 一个是Polygon类上的方法。另一个是该方法内的局部变量。您的代码中没有类属性。

于 2012-08-20T02:11:51.553 回答