簡體   English   中英

使用python with-statement進行currying?

[英]Currying using python with-statement?

我不確定這是否是“好的python練習”,但是可以定義一個自定義的File-object,可以執行以下操作:

myfile = myopen('myfile.txt')
with myfile:
    write('Hello World!') #notice we don't put "myfile.write(..)" here!

"write()" so that we don't have to type myfile.write(..) etc. It saves typing and makes the purpose clearer in some cases. 即文件上下文創建一個 “write()”,這樣我們就不必輸入myfile.write(..)等。它可以節省輸入並在某些情況下使目的更清晰。 例如:

myboard = ChessBoard()
with ChessBoard():
    make_move("e4")
    make_move("e5")
    give_up()

而不是

myboard = ChessBoard()
with ChessBoard():
    make_move("e4",board=myboard)
    make_move("e5",board=myboard)
    give_up(board=myboard)

問題是:我應該這樣做嗎? 我該怎么做? 我猜我必須以某種方式修改globals() - dict,但這似乎是一個壞主意..

編輯:好的,謝謝! 我得到了許多好的答案,建議我不要這樣做。 所以我不會這樣做:o)

這不是上下文管理者的意思,正如已經說過的那樣,我打敗了“明確勝於隱性”的原則。 使其工作的唯一方法是必須解決Python的組合語義,這是它的優點之一。 如果只有一種方法可以多次調用,那么你可以做些什么來節省輸入:

move = ChessBoard().make_move
move("e4")
move("e5")

或者使用多種方法:

board = ChessBoard()
move = board.make_move
give_up = board.give_up
# call methods

(在FP術語中,這實際上是部分應用,而不是currying。)

你認為你需要修改globals() 但是如果您在與您正在使用的模塊不同的模塊中定義了上下文管理器,那么您將使用模塊的全局變量來定義它。 不是使用它的模塊。 因此,您需要在__builtin__命名空間(內置函數所在的位置)中定義方法。 這肯定可以做到,但它讓我覺得更糟糕, 特別是如果你想用任意對象。 也許如果你以某種方式破壞了名稱(例如,添加一個前導下划線)。 但即便如此,如果嵌套with語句會怎么樣?

您正在尋找Python的with語句像帕斯卡或Visual Basic的,它只是不一樣的東西都沒有。 也就是說,一個等同於Pascal / VB with語句的Python將是一個可愛的東西; 它只是不能稱其with

首先,這不是一個好主意。 明確比隱含更好 - 通過明確提到董事會,讀者(可能是你幾個星期!)可以立即告訴哪個董事會正在進行操作。 此外,沒有必要。 您可以通過其他方式獲得更方便的語法:例如,創建單個對象的函數方法。 並刪除無意義的上下文管理器(它應該做什么?你已經預先創建了一個對象!)。

要做到這一點,你需要全局狀態,但不是globals明確。 比如,一個全局(模塊級別准確)對象堆棧,上下文管理器推送和彈出對象,各個函數查看該堆棧的頂部。 如果你知道你的東西,它實際上並不難實現,但正如我之前所說,沒有理由。

一種(至少半瘋狂)的方式是這樣的:

@contextmanager
def export(obj, *atts):
    yield [getattr(obj, a) for a in atts]

然后:

class X:
   def foo...
   def bar...

with export(some_x, 'foo', 'bar') as (foo, bar):
      foo() <-- some_x.foo
      bar() <-- some_x.bar

當然,像任何其他類似的解決方案一樣,這在現實生活中毫無意義。

正如其他人所提到的,這可能是一個非常糟糕的主意,但我確實看到了一些有限的案例(可能是一個轉移DSL),它可能是可行的。

class ChessBoard(object):
    def __init__(self, filename):
        self.filename = filename
    def __enter__(self):
        self.handle = open(self.filename, 'w')
        globals()['move'] = self.move
        globals()['give_up'] = self.give_up
    def __exit__(self, type, value, traceback):
        self.handle.close()
    def move(self, move):
        self.handle.write(move + '\n')
    def give_up(self):
        self.handle.write('resign' + '\n')

with ChessBoard('chess.txt'):
    move('e4')
    move('e5')
    give_up()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM