Python中的自变量与类变量
你能在下面的课程中澄清周长变量吗 我知道Python中的自变量与类变量,python,Python,你能在下面的课程中澄清周长变量吗 我知道self.vertices是针对特定实例的。既然周长没有用self定义,这是否意味着它是一个类变量?那么,不是所有的实例都有这种情况吗 将周长编码为self.permiture,这样就可以恰当地向每个实例声明周长,这难道不是正确的方法吗 这段代码来自一本书 多边形.py 新型 import math class Point: def __init__(self, x, y): self.x = x self.y =
self.vertices
是针对特定实例的。既然周长
没有用self
定义,这是否意味着它是一个类变量?那么,不是所有的实例都有这种情况吗
将周长编码为self.permiture
,这样就可以恰当地向每个实例声明周长,这难道不是正确的方法吗
这段代码来自一本书
多边形.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 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())
在您的代码中,有两个东西称为
周长
。一个是Polygon
类上的方法。另一个是该方法内部的局部变量。代码中没有类属性。不,这意味着它是本地的。另外,您不希望使用self.permiture
,因为它将使用相同的名称对方法进行阴影处理。使用some_name=…
分配一个新变量总是在最里面的封闭范围内创建变量(除非全局
或非局部
起作用,但它们在这里不相关)。在对象上指定新属性名称将在该对象上创建属性
因此self.foo=1
在当前由self
引用的对象上分配一个名为foo
的属性。通常,名称self
用作方法的第一个参数,该方法接收调用该方法的对象。所以“用self定义变量”并不是什么特别的事情;这只是分配给现有对象属性的一般规则。实例对象本身中存在的任何属性显然都必须特定于该实例
permiture=0
类的permiture
方法内部在最内层的封闭范围内创建变量。这是周长
方法,因此它创建了一个局部变量。局部变量只在函数调用期间存在,因此它既不是类变量,也不是实例变量。您不能从任何地方访问它,除非在该特定方法的范围内(并且它在每次调用时都有一个新的完全独立的值),因此它不能对所有实例都通用。但也不能在每个特定实例上访问不同的值,因此它也不是实例变量
如果在类块本身的方法外部有permiture=0
,则最内部的封闭范围将是类块这将创建一个“类变量”,它只是类对象上的一个属性。如果一个属性在一个类上,那么显然它不能特定于任何实例,因为只有一个类,但可以有任意数量的实例。另一方面,这正是多边形
类的初始化
、添加点
和周长
方法的内容;它们在类块中被赋值(使用def
语句),因此它们成为类对象的属性
总结:
self.foo=1
正在分配给当前由self
引用的对象上的属性(这通常是“当前实例”)foo=1
正在创建所定义类的类属性foo=1
正在创建所定义函数的局部变量foo.bar.baz=1
)就是写入对象的属性foo=1
,就是在最里面的封闭范围内写入一个变量我已经使用self.permiture进行了编码,上面两种类型有什么不同…哪种方法是正确的?拥有一个同名的方法和变量只是自找麻烦,因为你(和解释器)很难理解你所指的是什么。我强烈建议您更改其中一个。我已经使用self.permiture进行了编码,上面两种类型有什么区别……哪种方法是正确的?@user1050619:为什么要将它放在对象上?这有什么用,特别是每次计算都是新的吗?谢谢Ben。这是一个很好的解释。还有一个问题。哪一个是计算周长的正确方法。将它作为实例变量(self.period)或函数变量(period)…它真的重要吗?一般来说,这取决于你的意图。在本例中,在计算方法的返回值时,您似乎将其用作临时变量,因此将其作为实例变量是很奇怪的。另外,它与方法具有相同的名称,因此如果您将其指定为对象的属性,则在调用一次方法后,您将无法再次调用该方法,因为
square.permiture
将获得属性permiture
,而不是方法,然后使用square.permiture()调用它
会给您一个错误。@user1050619:要添加一些稍微强一点的建议,局部变量和实例变量确实很重要。他们做完全不同的事情。如果一个局部变量可以满足您的要求,那通常就是您应该使用的。使用局部变量要容易得多,因为您只需查看一个函数的代码,就可以了解如何使用它。实例变量可以从其他方法访问,甚至可以完全从类外部访问。@user1050619我还希望实例变量是实例“定义”的一部分;确定此特定实例所需的数据。周长听起来不像是特定多边形定义的一部分;相反,它应该根据定义多边形的信息(多边形列表)进行计算
>>> 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())