2016-04-27 13 views
2

関数にパラメータとして渡された変数に新しい値を代入することはできません。代入を関数に置き換える方法

>>> a = 1 
>>> def foo(bar): 
...  bar = 2 
... 
>>> foo(a) 
>>> a 
1 

ただし、方法で変更することは可能です。

>>> a = [1, 2] 
>>> def foo(bar): 
...  bar.append(3) 
... 
>>> foo(a) 
>>> a 
[1, 2, 3] 

しかし、代入を置き換える(変数に全く新しい値を与える)方法があります。私の最初の例を動作させるために何か:

>>> a = 1 
>>> def foo(bar): 
...  bar.assign(2) 
... 
>>> foo(a) 
>>> a 
2 

私が見つけた唯一の選択肢は、グローバル変数ですと私自身のクラスを設計します。

だから私の質問は以下のとおりです。

  1. は、このような方法はありますか? (または代替?)

  2. もしそうでなければ、私は見落としよりもデザインの選択肢が必要です。なぜこの選択​​?値/コンテンツの一部を変更するメソッドがある場合、新しい値/コンテンツ全体を置き換える/与える方法はなぜありませんか?

+2

代わりに、関数から変更された値を返し、その値を変数に代入することもできます。 – muratgu

+0

http://stackoverflow.com/a/7028618/6258347には、Pythonでできることがいくつかあります。子供を覚えて、家で試してはいけません。 – Pykler

答えて

2

すべてがオブジェクトであり、 Pythonのオブジェクトは変更できません。文字列、数値(int、float)のような基本型は変更可能ではありません。 1は常に1であり、決して他のものを作ることはできません。

これは実際にはほとんどのいわゆるオブジェクト指向言語の場合であり、より多くの最適化です。

あなたが言ったように、新しいオブジェクトの内部を変更するために不変型をラップする独自のオブジェクトを作成する必要があります。あなたも、あなたが言及した他のポスターの一部として

>>> a = Mutatable(1) 
>>> def foo(bar): 
...  bar.assign(2) 
... 
>>> foo(a) 
>>> a.value 
out: 2 

を言うことができるあなたの例から今この

class Mutatable: 
    def __init__(self, value): 
     self.value = value 
    def assign(self, value): 
     # in python you cannot overload the = (assignment) operator 
     self.value = value 

を行うには非常に単純なクラスを作成することができます。 一般的なプログラミングアドバイス。突然変異を過度に使用すると、アプリケーションをデバッグするのが非常に難しくなります。値を返し、例外を送出する関数は、テストとデバッグが簡単です。

+0

最後に良いアドバイスがあります – Pykler

+0

これは、すべてのオブジェクト値を変更することができれば、ナンセンスである '1'に' 2'を割り当てることができるということです。 ( 'a = 1 '、それ以上は' 'a' *が*' 1''で '' a''は '' a''を含む/価値がありますか? – vmonteco

1

まず第一に、Pythonではあらゆるすべてのものは、スコープに(いくつかのシングルトンとインターンを除く)オブジェクトとすべてのオブジェクトが存在しているグローバル、ローカル、ビルトインと囲むスコープが含まれています。スコープを使用する主な目的は、明らかに、特定の目的に従った一連のコマンドとスクリプトを保持することです。

したがって、異なるスコープの変数を互いに影響させることで、このアーキテクチャを破壊することは妥当ではありません。

しかし、Pythonでは、文のように、一部の変数を上限スコープで利用できるようにするためのツールが用意されています。

:第二の例については、関数内で可変オブジェクトを変更すると、発信者に影響を与える可能性があることを覚えていて、リストのような変更可能なオブジェクトが実際に実際のオブジェクトへのポインタのコンテナであるため、それだと、変更1それは主オブジェクトに影響します。


1外へ内側からPythonでスコープの階層がある:ローカル、グローバル、組み込みを囲みます。 LEGB方式として知られています。

1

これは2つの設計上の決定の結果です。まず、Pythonの関数引数はpassed by assignmentです。それは大体

bar = a 
<function body, verbatim> 

あなたは同じようにあなただけの任意の変数へのポインタを渡すことができない理由、たとえば、C.だこと、あなたが

foo(a) 

のようなコールを持っている場合、それはに変換、です関数の引数を変更する場合は、変更可能な内部構造が必要です。Pythonの整数は、は不変であり、他の種類の数字、文字列またはタプルも含まれます。私はこの決定の元の動機を知らないが、私は2つの主な利点を見ている:

  • 人間がコードについて推論するのが楽になる(あなたの整数が魔法のように変わることはない関数の引数の多くは単なる数字や文字列

あるので、私の個人的な意見は、あなたがすべきことで、最適化または静的解析の目的のためのコード()について推論するために、コンピュータのための機能)

  • 簡単に可能であれば引数を変更する関数は避けてください。少なくとも、メソッドであり、対応するオブジェクトを変更する必要があります。そうしないと、コードがエラーを起こしやすくなり、保守とテストが難しくなります。したがって、私はこの不変性を完全にサポートし、どこでも不変のオブジェクトを使用しようとします。

  • 1

    あなたがglobalまたはreturn指示なしに、いくつかの関数内の変数の値を変更したい場合は、あなたが関数のパラメータでその名前を渡し、globals()を使用することができます:pythonで

    >>> def foo(bar): 
        globals()[bar] = 3  
    
    >>> x = 7 
    >>> x 
    7 
    foo('x') 
    >>> x 
    3 
    
    関連する問題