1. ホーム
  2. パイソン

[解決済み】Pythonの変数宣言

2022-03-17 06:18:48

質問

学習 パイソン と、基本的な疑問を持っています。

1.私が見たのは 変数宣言 (ここにあるパス)のように

class writer:
    path = ""

明示的な宣言がなくとも __init__ .

def __init__(self, name):
    self.name = name

の目的は理解しています。 __init__ しかし、他の関数で変数を宣言することは推奨されますか?

2.カスタムタイプを保持する変数を作成するにはどうすればよいですか?

class writer:
    path = "" # string value
    customObj = ??

解決方法は?

では、まず最初に。

Pythonにはquot;変数宣言やquot;変数初期化というものは存在しません。

単に「代入」と呼んでいるものがありますが、「命名」と呼ぶべきでしょう。

アサインとは、「左辺のこの名前は、右辺を評価した結果を参照するようになった。

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

このように、Pythonの名前(変数よりも良い言葉です)には関連する型がありません。型に関係なく同じ名前をつけることができますが、その型に依存した振る舞いをすることに変わりはありません。名前は、単に値(オブジェクト)を参照するためのものです。これが2番目の質問の答えです。あなたは はしない。 は、カスタムタイプを保持するために変数を作成します。特定の型を保持するために変数を作成することはありません。あなたは、変数を全く作成しません。オブジェクトに名前を付けるのです。

2点目。Pythonはクラスに関して非常にシンプルなルールに従っており、Java、C++、C#などの言語が行っていることよりも、実際にはずっと一貫性があります。 の中で宣言されたものはすべて class ブロックはクラスの一部です。 . そのため、関数 ( def ここで書かれているのはメソッド、つまりJavaやC++、C#と同じようにクラスオブジェクトの一部(インスタンス単位では保存されない)です。しかし、ここでの他の名称は、以下の通りです。 また はクラスの一部です。繰り返しますが、名前は単なる名前であり、関連する型はありませんし 関数もオブジェクトである をPythonで作成しました。このように

class Example:
    data = 42
    def method(self): pass

クラスもオブジェクト , Pythonで。

さて、これで オブジェクト という名前の Example であるすべてのもののクラスを表す。 Example s. このオブジェクトは、ユーザが提供する2つの 属性 (C++では "members" C#では "fields or properties or methods" Javaでは "fields or methods" )があります。そのうちの1つは、名前が data という整数値が格納されています。 42 . もう一方は method これは関数オブジェクトを格納します。(Pythonが自動的に追加する属性は他にもいくつかあります)。

しかし、これらの属性はまだ本当の意味でオブジェクトの一部ではありません。基本的にオブジェクトは、これ以上分割できないものまで、より多くの名前(属性名)を束ねたものに過ぎないのです。そのため、あるクラスの異なるインスタンス間や、意図的に設定すれば異なるクラスのオブジェクト間で値を共有することができます。

インスタンスを作ってみましょう。

x = Example()

という名前の別のオブジェクトを用意しました。 x のインスタンスです。 Example . その datamethod は実際にはオブジェクトの一部ではないのですが、それでも x これは、Pythonが裏で行っているマジックです。私たちが method 特に、quot;bound method"を代わりに取得します(呼び出した場合。 x として自動的に渡されます。 self を検索すると、このようなことは起こりえません。 Example.method を直接入力)。

を使おうとするとどうなるのでしょうか? x.data ?

調べるときは、まずオブジェクトの中で調べます。オブジェクトで見つからなければ、Pythonはクラスで探します。

しかし、私たちが 割り当てる x.data Pythonはオブジェクトに属性を作成します。それは ではなく はクラスの属性を置き換えます。

これによって オブジェクト を初期化します。Pythonは自動的にクラスの __init__ メソッドがあれば、新しいインスタンスが作成されたときにそれを実行します。このメソッドでは、単純に属性に代入して、各オブジェクトにその属性の初期値を設定することができる。

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

ここで name を作成する際に Example であり、各インスタンスはそれぞれ name . Python は class 属性を無視します。 Example.name を検索するたびに .name というのも、インスタンスの属性が最初に見つかるからです。

最後にもう一つ、注意点があります。 修正(突然変異)と代入は違うものです!

Pythonでは、文字列は不変です。変更することはできません。そうすると

a = 'hi '
b = a
a += 'mom'

あなた 変更しない は、元の 'hi ' 文字列です。Pythonでは不可能なことです。その代わりに 新しい 文字列 'hi mom' となり、原因 a の名前であることをやめる。 'hi ' の名前であり、 'hi mom' の代わりに 私たちは b の名前です。 'hi ' を再適用した後、同様に a という名前を付けます。 b は、やはり 'hi ' というのも 'hi ' はまだ存在し、変更されていない。

しかし、リストは変更することができます。

a = [1, 2, 3]
b = a
a += [4]

現在 b は[1, 2, 3, 4]でもあります。 b と同じものを表す名前です。 a という名前をつけて、そのものを変更しました。のために新しいリストを作ったわけではありません。 a を名前に付けることができます。 += はリストとは異なります。

なぜなら、クラス属性としてリストを持っていて、あるインスタンスを使ってリストを変更した場合、その変更は他のすべてのインスタンスで "see"されるからです。これは、(a) データは実際にはクラスオブジェクトの一部であり、どのインスタンスオブジェクトでもない、(b) 単純な割り当てではなく、リストを変更しているため、クラス属性を隠す新しいインスタンス属性を作成していない、からです。