6

これは簡単な質問かもしれませんが、私はそれを独自に検索するのに苦労しています。

静的ディクショナリを定義するクラスがあり、そのディクショナリのサブセットを静的に定義しようとします。

だから、おもちゃの例として:

class example(object): 
    first_d = {1:1,2:2,3:3,4:4} 
    second_d = dict((k,first_d[k]) for k in (2,3))

これにより、 NameError: global name 'first_d' is not defined

この参照をどのように行う必要がありますか?このパターンは他の場合にも機能するようです。例:

class example2(object):
    first = 1
    second = first + 1
4

3 に答える 3

5

基本的なリスト内包表記には次の構文があります

[expression for var in iterable]

リスト内包表記がクラス内で発生すると、クラスの属性を で使用できますiterable。これは、Python2 と Python3 に当てはまります。

ただし、クラスの属性は Python2 では使用 (アクセス) できますがexpression、Python3 では使用できません。

ジェネレータ式の場合、話は少し異なります。

(expression for var in iterable)

クラス アトリビュートには引き続き からアクセスできますがiterable、クラス アトリビュートには からアクセスできませんexpression。(これは Python2 と Python3 に当てはまります)。

これはすべて次のように要約できます。

                             Python2      Python3
Can access class attributes
--------------------------------------------------
list comp. iterable                Y            Y
list comp. expression              Y            N
gen expr. iterable                 Y            Y
gen expr. expression               N            N
dict comp. iterable                Y            Y
dict comp. expression              N            N

(辞書内包表記は、この点でジェネレーター式と同じように動作します。)


これはあなたの質問にどのように関係していますか:

あなたの例では、

second_d = dict((k,first_d[k]) for k in (2,3))

aは、ジェネレーター式の一部からアクセスできないNameErrorために発生します。first_dexpression

Python2 の回避策は、ジェネレータ式をリスト内包表記に変更することです。

second_d = dict([(k,first_d[k]) for k in (2,3)])

ただし、このコードは Python3 では失敗するため、これはあまり快適な解決策ではありません。

Joel Cornett が提案するように、次のことができます。

second_d = {k: v for k, v in first_d.items() if k in (2, 3)}

これは、辞書内包表記の一部ではなく、を使用first_dするためです。ただし、多くのアイテムが含まれている場合、これは必要以上に多くのアイテムをループする可能性があります。それにもかかわらず、このソリューションは が小さい場合には問題ないかもしれません。iterableexpressionfirst_dfirst_d

一般に、クラスの内部または外部で定義できるヘルパー関数を定義することで、この問題を回避できます。

def partial_dict(dct, keys):
    return {k:dct[k] for k in keys}

class Example(object):
    first_d = {1:1,2:2,3:3,4:4}
    second_d = partial_dict(first_d, (2,3))

class Example2(object):
    a = [1,2,3,4,5]
    b = [2,4]
    def myfunc(A, B):
        return [x for x in A if x not in B]
    c = myfunc(a, b)

print(Example().second_d)
# {2: 2, 3: 3}

print(Example2().c)
# [1, 3, 5]

関数はローカル スコープを定義し、このローカル スコープ内の変数に辞書内包表記内からアクセスできるため、機能します。

これはhere で説明されましたが、リスト内包表記、ジェネレーター式、または dict 内包表記expressionの部分とは異なる動作をする理由が説明されていないため、私はこれに完全に満足しているとは言えません。iterable

したがって、 Python がこのように振る舞う理由を (完全に) 説明することはできません。

于 2012-08-02T21:52:16.863 に答える
1

少し厄介ですが、これを試すことができます:

class test(object):
    pass

test.first = {1:1, 2:2, 3:3, 4:4}
test.second = dict((k, test.first[k]) for k in (2,3))

...その後:

>>> test.first
{1: 1, 2: 2, 3: 3, 4: 4}
>>> test.second
{2: 2, 3: 3}

>>> t = test()
>>> t.first
{1: 1, 2: 2, 3: 3, 4: 4}
>>> t.second
{2: 2, 3: 3}

>>> test.first[5] = 5
>>> t.first
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
于 2012-07-31T22:08:18.110 に答える
0

定義の最後に到達するまで、クラスは存在しないと思います。

于 2012-08-02T17:26:55.523 に答える