2010-10-14 13 views
0

下面的代碼可以在Python 2.6和3.1下運行,但SomeObject.columns的第三個lambda有點愚蠢,沒有真正的目的,但是爲了防止在類聲明結束之前查看對SomeObject.helper_function的引用。這似乎是一個黑客。如果我刪除了lambda,並用SomeObject.helper_function替換它,我會得到NameError: name 'SomeObject' is not defined。我錯過了一個更好的非哈克方式嗎?在Python中,任何優雅的方式來引用類聲明範圍內的類方法?

class SomeObject: 
    def __init__(self, values): 
    self.values = values 

    @staticmethod 
    def helper_function(row): 
    # do something fancy here 
    return str(len(row)) 

    columns = [ 
    (lambda x: x['type'], 'Type'), 
    (lambda x: 'http://localhost/view?id=%s' % x['id'], 'Link'), 
    (lambda x: SomeObject.helper_function(x), 'Data'), 
    ] 

    def render_table_head(self): 
    print('\t'.join([c[1] for c in self.columns])) 

    def render_table_body(self): 
    for row in self.values: 
     print('\t'.join([col[0](row) for col in self.columns])) 

回答

4

沒有辦法引用當前正在定義的類。應該真的有關鍵字引用當前範圍,例如。 __this_class__爲最內層的類定義,__this_func__爲最內層的函數,所以類和函數可以乾淨地引用自己而不必重複它們的名字。

你可以移動列的定義出來的類主體的:

class SomeObject: 
    def __init__(self, values): 
     self.values = values 
    ... 

SomeObject.columns = [ 
    (lambda x: x['type'], 'Type'), 
    (lambda x: 'http://localhost/view?id=%s' % x['id'], 'Link'), 
    (SomeObject.helper_function, 'Data'), 
] 

順便說一句,請始終使用至少4空間縮進。更少的東西很難閱讀。

+0

FWIW,我從來沒有遇到問題,指的是由名稱定義的函數。該代碼實際上並沒有運行,直到名稱被定義。我錯過了什麼嗎? – aaronasterling 2010-10-14 03:06:56

+0

@Aaron:這不會給你這個函數本身,它會給你任何綁定這個名字的東西;例如,如果函數是裝飾的,或者包含的範圍因爲某些其他原因而更改,則這是不同的。 *一般*這就是你想要的,但我認爲你應該能夠在一般情況下獲得對「這個對象」的引用,而不必按名稱查找自己。 – 2010-10-14 03:15:42

+0

是的,我注意到之前缺少這些關鍵字,但是我認爲我對它們的渴望是C/C++污染心靈的產物,並設法找到完美的優雅替代品。這是第一次看起來沒有。 – 2010-10-14 03:29:22

0

爲什麼不填充init()中的列並使用self?

def __init__(self, values): 
    self.values = values 
    self.columns = [ 
     (lambda x: x['type'], 'Type'), 
     (lambda x: 'http://localhost/view?id=%s' % x['id'], 'Link'), 
     (self.helper_function, 'Data'), 
    ] 
+3

這些是實例變量,而不是類變量。 – 2010-10-14 02:37:48

0

This works。這違背了我所有的感受。

class SomeObject: 
    def __init__(self, values): 
    self.values = values 

    def helper_function(row): 
    # do something fancy here 
    return str(len(row)) 

    columns = [ 
    (lambda x: x['type'], 'Type'), 
    (lambda x: 'http://localhost/view?id=%s' % x['id'], 'Link'), 
    (helper_function, 'Data'), 
    ] 

    def render_table_head(self): 
    print('\t'.join([c[1] for c in self.columns])) 

    def render_table_body(self): 
    for row in self.values: 
     print('\t'.join([col[0](row) for col in self.columns])) 


if __name__ == '__main__': 
    print "foo" 

    o = SomeObject([{'type':'type100', 'id':'myId'}, {'type':'type200', 'id':'myId2'}]) 
    o.render_table_body() 
+0

你是怎麼想的?它的倒行逆施,但以一種非常微妙的方式。令我驚訝的是,擁有一個自我更少的classmethod實際上可以解決問題! – 2010-10-14 03:19:40

+0

我把你的代碼扔進pycharm,並開始嘗試。起初我想重現你的發現。然後我試圖避免將代碼放入__init__中。我同意,這是不正當的! – kevpie 2010-10-14 03:35:50

0

您可以直接通過

(helper_function.__func__, 'Data'), 

指靜態的功能,而無需改變任何東西在你的代碼。 helper_functionstaticmethod類型,並且__func__允許訪問基礎功能。

相關問題