0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonの名前隠し

Last updated at Posted at 2025-09-13

Pythonでの同じ名前の関数や変数を複数宣言するにはいくつか方法がありますが、呼び出しがどうなるかを把握するためのメモです。
環境はMac OS 15.6.1+Python 3.13.7です。

結論

ローカル変数とグローバル変数

  • グローバル変数と同じ名前の関数内ローカル変数を宣言すると、ローカル変数のみアクセス可能
  • ネストした関数の内側で外側のローカル変数と同じ名前のローカル変数を宣言すると、内側のみアクセス可能
  • ネストした関数の内側でnonlocal宣言すると外側と内側で同じ変数になる

class内の同じ名前のmethod

  • instance methodを宣言するとclassmethod, staticmethodは呼べなくなる
  • classmethod, staticmethodは後で宣言した方が有効

super()による親クラスの呼び出し

  • 関数はMRO順の親クラスになり、菱形継承も問題なく処理できる
  • selfやclsは子クラスのまま。親クラスの変数にキャストされない
    呼び出された親クラスの関数内でself, clsを使うときに要注意

(提案)定数宣言の関数による代替

  • グローバル変数・クラス変数の書き換えを阻止できる
  • super()を利用すると親クラスの関数が呼ばれるので、戻る定数値も親クラスの値になる

名前隠しの利点

  • 文脈が同じなら同じ名前にできるため、覚える関数名や変数名が少ない
  • インターフェイスを揃えれば多態性を利用して複数の処理をまとめられる
  • 他の処理からアクセスして欲しくない関数や変数を隠すことができる

名前隠しのやり方

  1. 関数のネスト

    def myfunc():
        myvalue = "myfunc_value"
    
        def myfunc():
            myvalue = "inner_value"
            print(myvalue)
    
  2. (実用上意味なし)staticmethod, classmethod, instance methodで同じ名前

    class myClass:
        @staticmethod
        def myfunc():
            print("staticmethod")
    
        @classmethod
        def myfunc(cls):
            print("classmethod")
    
        def myfunc(self):
            print("instance method")
    
  3. (実用上意味なし)staticmethod, classmethodで同じ名前

    class myClass:
        @staticmethod
        def myfunc():
            print("staticmethod")
    
        @classmethod
        def myfunc(cls):
            print("classmethod")
    
  4. グローバル・クラス・インスタンス・ローカルで同じ名前の変数

    myvalue = "global value"
    
    class myClass:
        myvalue = "class value"
        def __init__(self):
            self.myvalue = "instance value"
        def test(self):
            myvalue = "local value"
    
  5. classの継承によるinstance methodの上書き

    class baseclass:
        myvalue = "base_class value"
    
        def myfunc(self):
            print("base instance method", self.myvalue, self.__class__.myvalue)
    
        def __init__(self):
            self.myvalue = "base instance value"
    
    
    class myclass(baseclass):
        myvalue = "my_class value"
    
        def myfunc(self):
            print("my instance method", self.myvalue, self.__class__.myvalue)
    
        def __init__(self):
            super().__init__()
            self.myvalue = "my instance value"
    
  6. classの継承によるclass methodの上書き

    class baseclass:
        myvalue = "base_class value"
    
        @classmethod
        def myfunc(cls):
            print("base instance method", cls.myvalue)
    
        def __init__(self):
            self.myvalue = "base instance value"
    
    
    class myclass(baseclass):
        myvalue = "my_class value"
    
        @classmethod
        def myfunc(cls):
            print("my instance method", cls.myvalue)
    
        def __init__(self):
            super().__init__()
            self.myvalue = "my instance value"
    

検証結果

  1. 関数をネストすると内側の変数が参照される
    内側でnonlocal宣言すると「外と同じ名前で別の変数」を使えなくなる
    def myfunc():
        myvalue = "myfunc_value"
    
        def myfunc():
            myvalue = "inner_value"
            print(myvalue) # inner_value
    
    myfunc()
    
  2. instancemethodを宣言すると同名のstaticmethod, classmethodは呼べなくなる
    myfunc()  # global method
    x = myClass()
    x.myfunc()  # insance method
    x.__class__.myfunc()  # Error
    myClass.myfunc()  # Error
    
  3. 同名のstaticmethod, classmethodは後のものが有効
    class myClass0:
        @staticmethod
        def myfunc():
            print("static method")
    
        @classmethod
        def myfunc(cls):
            print("class method")
    
    
    class myClass1:
        @classmethod
        def myfunc(cls):
            print("class method")
    
        @staticmethod
        def myfunc():
            print("static method")
    
    
    myClass0.myfunc()  # class method
    myClass1.myfunc()  # static method
    
  4. globalと関数内localで同じ名前の変数を宣言すると、localしか呼べない
    myvalue = "global value"
    
    class myClass:
        myvalue = "class value"
    
        def __init__(self):
            self.myvalue = "instance value"
    
        def test(self):
            myvalue = "local value"
            print(myvalue) # local value
            print(self.myvalue) # instance value
            print(self.__class__.myvalue) # class value
    
    x = myClass()
    x.test()
    
    
  5. super()を使っても、呼び出し先のselfの中身は子クラス
    class myclass(baseclass):
        ...
        def test(self):
            print(super().myvalue)
            print(super().myfunc())
    
    x = myclass() # base_class value
    x.test() # base instance method, my instance value, my_class value
    
  6. super()を使っても、呼び出し先のclsの中身は子クラス
    class myclass(baseclass):
        ...
        def test(self):
            print(super().myvalue)
            print(super().myfunc())
    
    x = myclass() # base_class value
    x.test() # base instance method, my_class value
    
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?