3

以下のクラスの境界変数について明確にしてください。

self.verticesは特定のインスタンスに対するものであることを理解しています。perimeterで定義されていないのでself、ここではクラス変数ということですか? それでは、すべてのインスタンスに共通ではありませんか?

境界を としてコーディングするのは正しい方法ではないself.perimeterので、各インスタンスに適切に宣言されますか?

このコードは本からのものです。

Polygon.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 = ...常に最も内側の囲みスコープに変数が作成されます (globalまたはが使用されている場合を除きnonlocalますが、ここでは関係ありません)。オブジェクトに新しい属性名を割り当てると、そのオブジェクトに属性が作成されます。

そのため、 によって現在参照されているオブジェクトself.foo = 1に指定された属性を割り当てます。通常、この名前は、メソッドが呼び出されたオブジェクトを受け取るメソッドの最初のパラメーターとして使用されます。したがって、「自己で変数を定義する」ことは特別なことではありません。これは、既存のオブジェクトの属性への割り当てに関する通常のルールです。インスタンスオブジェクト自体に存在する属性は、明らかにそのインスタンスに固有のものでなければなりません。fooselfself

perimeter = 0クラスのperimeterメソッド内Polygonで、最も内側のスコープに変数を作成します。それがperimeterメソッドなので、ローカル変数を作成します。ローカル変数は、関数呼び出しの間だけ存在するため、クラス変数でもインスタンス変数でもありません。その特定のメソッドのスコープ内以外の場所からアクセスすることはできません (また、呼び出しごとに新しい完全に独立した値を持ちます)。そのため、すべてのインスタンスに共通することはできません。ただし、特定のインスタンスごとに異なる値にアクセスすることもできないため、インスタンス変数でもありません。

perimeter = 0クラスブロック自体にメソッドの外側がある場合、最も内側の囲みスコープはクラスブロックになります。これにより、クラス オブジェクトの単なる属性である「クラス変数」が作成されます。属性がクラスにある場合、クラスは1 つしかありませんが、インスタンスはいくつでも存在できるため、明らかにインスタンスに固有ではありません。余談ですが、これはまさにクラスの__init__add_point、およびperimeter メソッドです。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

あなたのコードには、 と呼ばれるものが 2 つありますperimeter。1 つはPolygonクラスのメソッドです。もう 1 つは、そのメソッド内のローカル変数です。コードにクラス属性がありません。

于 2012-08-20T02:11:51.553 に答える