質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.96%

Pythonでオブジェクトのプロパティに変数でアクセス

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 2,074

score 123

phpでは、以下の様に変数にプロパティ名を代入して、オブジェクトのプロパティの値を取得することができます。

<?php
class Test {
    public $textProperty;
    function Test($textValue) {
        $this->textProperty = $textValue;
    }
}
$inst = new Test('テキスト');
$propertyName = 'textProperty';
printf('%s'."\n", $inst->$propertyName);
?>


このような記述をPythonで実施することはできますでしょうか?
私の浅いPythonの経験と知識では、以下の様なリフレクション的な記述で値を取得することぐらいしか思いつきません。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from sys import stdout
class Test:
    textProperty = None
    def __init__(self, textValue):
        self.textProperty = textValue
def main():
    inst = Test('テキスト')
    propertyName = 'textProperty'
    stdout.write('%s\n' % getattr(inst, propertyName))
if(__name__ == '__main__'):main()


このPythonのコードをphpに直すと以下のようになると思います。

<?php
class Test {
    public $textProperty;
    function Test($textValue) {
        $this->textProperty = $textValue;
    }
}
$inst = new Test('テキスト');
$propertyName = 'textProperty';
printf('%s'."\n", $inst->__get($propertyName));
?>


このようなリフレクション的な記述ではなく、最初のphpの記述のように、コードベース(=関数等を使わない)で値を取得するようなコードの記述は、Pythonで可能でしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+4

これは可変変数という機能なのですが、大変珍しい機能でして、私の知る限り、この機能を実装しているメジャーなプログラミング言語はPHP以外にありません※。Pythonにももちろんありませんので、__get()getattr()__dict__等でリフレクションを使うか、eval()で無理矢理するかしかありません。

※ JavaScriptはinst[propertyName]のように書けないことがないですが、a.ba["b"]が同じであるという解釈ですので可変変数とは少し異なりますし、PHPのように$$aみたいなローカル変数に可変変数を使うことはできません。
※ 一部のBashで${!a}みたいにできるらしいのですが、未確認です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/25 09:12

    「可変変数」ですか! 独学でトライアンドエラーで学習する癖があり、正式な名称を知る機会がありません。ありがとうございます。
    Pythonでは「可変変数」がないこと、了解いたしました。リフレクション的な処理で実装することに致します。

    P.S.
    > メジャーなプログラミング言語はPHP以外にありません

    Cなどのレガシーな言語ですとポインタやポインタのポインタなどが近いですね。

    キャンセル

+3

"textProperty"という文字列でもって、同名のメンバにアクセスしたいということですよね。
私が思いつく範囲で一番近いのは __dict__ ですかね。
メソッドの方は getattrしか思いつきません。

class Test:
  textProperty = None   # ちなみにこれはclass変数になるので不要です。
  def __init__(self, textValue):
    self.textProperty = textValue

  def add(self,x,y):
    return x + y

if __name__ == '__main__':
  t = Test("abc")
  prop_name = "textProperty"
  method_name = "add"

  print(t.__dict__[prop_name])
  # print(Test.textProperty)    # None
  print(getattr(t, method_name)(2,3))
> python sample.py
abc
5

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/25 09:10

    ご回答ありがとうございます。
    Pythonでは、ご提示いただいた__dirct__()や__getattr__()を使用して実装するしかなさそうですね。
    頂いたご回答から、「class変数」「__dict__()」を知ることができました。ありがとうございます。

    キャンセル

0

ええっと、こういうことではなくてですか?

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from sys import stdout
class Test:
    textProperty = None
    def __init__(self, textValue):
        self.textProperty = textValue
def main():
    inst = Test('テキスト')
    stdout.write('%s\n' % inst.textProperty) # <--
if(__name__ == '__main__'):main()

9.3.5. Class and Instance Variables from python tutorial

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/25 07:39

    ご回答ありがとうございます。

    ご提示いただいたコードがもっともシンプル(かつ美しい)コードです。

    しかしながらそのコードはプロパティ名称が予め分かっていて、かつ不変である必要があります。

    とある処理の汎用部品を作成しており、プロパティ名称は、コマンド引数やXML等のパラメータファイルから取得する予定です。

    前提をお伝えしていなくて申し訳ありませんでした。

    キャンセル

  • 2016/08/25 11:01

    あー、完全に題意を読み違えていました。申し訳ないです。

    それ以外だと他の方の回答の通り、__dict__でアクセスするか、__getattr__あたりを使うぐらいしか思いつきませんでした。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る