请您澄清一下下面的班级变量。
我理解self.vertices
是针对特定实例的。由于perimeter
未定义为self
,这是否意味着它是一个类变量?那么所有实例都不常见吗?
这不是将边界编码为self.perimeter
的正确方法,因此它适当地声明为每个实例吗?
此代码来自一本书。
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())
答案 0 :(得分:4)
使用some_name = ...
分配新变量始终会在最里面的封闭范围内创建变量(除非global
或nonlocal
正在播放,但它们在此处不相关)。在对象上分配新属性名称会在该对象上创建属性。
因此self.foo = 1
会在foo
当前引用的对象上分配名为self
的属性。通常,名称self
用作方法的第一个参数,该方法接收调用该方法的对象。所以“用自己定义一个变量”并不是什么特别的东西;它只是关于在现有对象上分配属性的普通规则。实例对象本身中存在的任何属性显然必须特定于该实例。
perimeter = 0
类的perimeter
方法中的 Polygon
在最里面的封闭范围内创建一个变量。这是perimeter
方法,因此它创建了一个局部变量。局部变量仅在函数调用期间存在,因此它既不是类变量也不是实例变量。除了在特定方法的范围内之外,您无法从任何地方访问它(并且它在每次调用时都有一个新的完全独立的值),因此它不是所有实例的共同点。但是你也不能在每个特定的实例上为它访问不同的值,因此它也不是实例变量。
如果你在方法之外的perimeter = 0
,在类块本身,那么最里面的封闭范围将是类块。 那会创建一个“类变量”,它只是类对象的一个属性。如果一个属性在一个类上,那么很明显它不能特定于任何实例,因为只有一个类但可以有任意数量的实例。顺便说一句,这正是__init__
类的add_point
,perimeter
和Polygon
方法的内容;它们被分配(带有def
语句)在类块中,因此它们成为类对象的属性。
要点:
self.foo = 1
正在分配self
当前引用的对象的属性(这通常是“当前实例”)foo = 1
在类块中创建正在定义的类的class属性foo = 1
正在创建正在定义的函数的局部变量但你不应该那样记住它。他们只是特例:
foo.bar.baz = 1
这样的虚线名称正在写入对象的属性foo = 1
之类的简单名称是写入最里面的封闭范围内的变量答案 1 :(得分:2)
不,这意味着它是本地的。此外,您不想使用self.perimeter
,因为它会使用相同的名称隐藏方法。
答案 2 :(得分:0)
在您的代码中,有两个名为perimeter
的内容。一个是Polygon
类的方法。另一个是该方法中的局部变量。您的代码中没有类属性。