1

私は現在、Tkinter GUI で 2 つのボールを動かし、他のことも行う小さなコードを書いています。私はすでに動作するコードを書いていますが、多くのグローバル変数を使用しているため、改善を試みました。以下に、質問に関連するコード セクションを貼り付けました。

can.coords には、「移動」したいオブジェクトと新しい座標の 5 つのパラメーターが必要です。moveLeft() と addThirty() の両方からの戻り値は、2 つの項目リストです。もちろん、(リストをアンパックするための) スター演算子は機能しません。

返された関数の 2 つのリストから 4 つの項目をメソッド .coords() に渡すにはどうすればよいですか?

PS : 私は Python だけでなく、プログラミングも初めてです。

def moveo (lr, tb):
    global newX, newY
    newX = x+lr
    newY = y+tb
    return newX, newY


def moveLeft ():
    coordins = moveo (-10, 0)
    return coordins

def addThirty (func):
    i = 0
    coordinsNew  = func
    coordinsNew = list(coordinsNew)
    while i < 2:
        coordinsNew[i] = coordinsNew[i]+30
        i += 1
    return coordinsNew

Button(wind, text = 'Left', command=can.coords (oval1,(*moveLeft()),(*addThirty(moveLeft()))))
4

3 に答える 3

1

両方の関数が同じ型 (リストまたはタプル) を返す場合は、次のようにします。

can.coords(oval1, *(moveLeft() + addThirty(moveLeft())))

それらが異なる型 (タプル、リスト、イテレータなど) を返す場合は、次のようにします。

args = list(moveLevt())
args.extend(addThirty(moveLeft()))
can.coords(oval1, *args)
于 2013-08-15T22:12:03.607 に答える
1

2 つのリストまたは 2 つのタプルをいつでも 1 つに組み合わせることができます+:

can.coords(oval1, *(moveLeft() + addThirty(moveLeft())))

異なるタイプのシーケンス (または反復子) がある場合でも、いつでもそれらを変換できます。

can.coords(oval1, *(moveLeft() + tuple(addThirty(moveLeft())))))

ただし、実際には一歩下がって、そもそもなぜこれが 1 行である必要があるのか​​を尋ねる必要があります。画面の右端からスクロールし、理解するために考えなければならないほど複雑な括弧が必要です。なぜこれをしないのですか:

top, left = moveLeft()
bottom, right = addThirty(moveLeft())
can.coords(oval1, top, left, bottom, right)

コメントでは、次のように言います。

ボタンを押すたびに座標を変えたいので、これはできません。したがって、ボタンは次のことを行う必要があります: 両方の関数を実行して座標を変更し、一度に can.coords () に渡します。

1 行に入れるだけでは、そうはなりません。あなたが書いた方法では、can.coords一度呼び出して、結果の戻り値をコマンドとして渡します。それはあなたが望むものではありません。渡す必要があるのは、これらすべてを行う関数です。

つまり、間違いなく複数の行に分割する必要があります。例えば:

def update_coords():
    top, left = moveLeft()
    bottom, right = addThirty(moveLeft())
    can.coords(oval1, top, left, bottom, right)
Button(wind, text = 'Left', command=update_coords)

それを 1 行に収める唯一の方法は、同等のlambdaorpartialを使用することになるため、呼び出しよりもさらに読みにくくなります。何かのようなもの:

Button(wind, text = 'Left', command=lambda: can.coords(oval1, *(moveLeft() + addThirty(moveLeft()))))

関数を渡すことと、関数を呼び出してその戻り値を渡すことの違いを説明するために、もっと簡単な例を見てみましょう。

>>> def foo():
...     return 2
>>> print(foo)
<function foo at 0x12345678>
>>> print(foo())
2

ここで、違いが何であるかはかなり明確なはずです。foo値が関数foo自体である式です。しかし、引数なしfoo()で呼び出すことによって値が決定される式であり、foo返されたもの (この場合は2) を使用します。

もう少し複雑にしても、違いはありません。

>>> def bar(x, y):
...     return x+y
>>> print(bar)
<function bar at 0x12345680>
>>> print(bar(2, 3))
6

したがって、それbar自体をどのように渡すことができるか、または6取得したものをどのように渡すことができるかは明らかですbar(2, 3)が、引数なしで呼び出すことができる関数を渡し、返されるものと同じものを返したい場合はどうすればよいbar(2, 3)でしょうか? まあ、あなたはそのようなものを持っていません。作成する必要があります。

これは 2 つの方法で行うことができます: 新しい関数を作成する:

>>> def new_function():
...     return bar(2, 3)

…または関数を部分的に評価する:

>>> new_function = partial(bar, 2, 3)

あなたのケースはいくつかの余分なしわを追加します:関数ではなくバインドされたメソッドから始めているため、新しい関数が実行されるたびに引数が評価されることを確認する必要があります( moveLeft()1回ではなく毎回2回呼び出すためです)毎回呼び出すのと同じくらい重要can.coordsです)、複雑な方法で取得する引数がたくさんあります。しかし、これらのしわのどれも物事を難しくしません。あなたはそれらを過ぎて見る必要があります:

>>> def new_function():
...     can.coords(oval1, *(moveLeft() + addThirty(moveLeft())))

(パーシャルは書くのがずっと難しくなります。パラメータを取得するためだけに一連の関数を一緒に構成する必要があり、これもパーシャルにする必要があります…しかし、パーシャルが Python で自明でない場合は常に、しようとしないでください。それを理解して、明示的な関数を書くだけです。)

于 2013-08-15T22:15:31.140 に答える
0

このトピックを掘り下げて申し訳ありませんが、別のトピックに関するユーザーからの興味深い回答の後、この質問への回答を改善すると思いました. 実際には、コマンドが関数を返す限り、引数付きの関数をコマンドに割り当てることができます。この場合、左右、下などごとに新しい関数を記述する必要がないため、多くの問題を回避できます。

ご覧のとおり、command に割り当てる関数に引数を使用できます。

command=move1(0,10)

楕円形がどのように機能するかを示すために、楕円形のコードを 1 つだけ書きました。

from tkinter import *

x1, y1 = 135, 135
x2, y2 = 170, 170



def move1 (x, y):
    def moveo1 ():
        global x1, y1
        x1, y1 = x1+x, y1+y
        can.coords (oval1, x1, y1, x1+30, y1+30)
    return moveo1



##########MAIN############

wind = Tk()
wind.title ("Move Da Ball")

can = Canvas (wind, width = 300, height = 300, bg = "light blue")
can.pack (side = LEFT,padx = 5, pady = 5)


oval1 = can.create_oval(x1,y1,x1+30,y1+30,width=2,fill='orange') #Planet 1
Button(wind, text = 'Left', command=move1(-10,0)).pack(padx = 5, pady = 5)
Button(wind, text = 'Right', command=move1(10,0)).pack(padx = 5, pady = 5)
Button(wind, text = 'Top', command=move1(0,-10)).pack(padx = 5, pady = 5)
Button(wind, text = 'Bottom', command=move1(0,10)).pack(padx = 5, pady = 5)


Button(wind, text = 'Quit', command=wind.destroy).pack(padx = 5, pady = 5)

wind.mainloop()
于 2013-09-03T16:54:17.280 に答える