1

私は攻撃と呼ばれる機能を持っています:

def attack(name,minmultiplier,maxmultiplier,critchance,attacker,attackee):
    print(attacker[0],"used",name)
    multiplier=random.randint(minmultiplier,maxmultiplier)
    crit=random.randint(critchance,100)
    if crit==100 and ((attacker[2]*multiplier*2)-attackee[3]) > 0:
        attackee[1]=attackee[1]-((attacker[2]*multiplier*2)-attackee[3])
    elif ((attacker[2]*multiplier)-attackee[3]) > 0:
        attackee[1]=attackee[1]-((attacker[2]*multiplier)-attackee[3])
    else:
        print("You fail to hit",attackee[0])
    print(attackee[0],"'s health after",attacker[0],"'s attack is",attackee[1])

そして、ここでボスとプレイヤーに対していくつかの実際の攻撃を行っています。

boss=["Greed",1000,10,10,1]
slashp=attack("slash",1,2,5,player,boss)
slashb=attack("slash",1,2,5,boss,player)
kick=attack("kick",1,1,1,player,boss)
aiattacklist=[slashb]
attacknamelist=["slash","kick"]
attackfunclist=[slashp,kick]

これらのバージョンを変数として保存しているだけですが、まだ呼び出されています:

template used slash
You fail to hit Greed
Greed 's health after template 's attack is 1000
Greed used slash
template 's health after Greed 's attack is 58
template used kick
You fail to hit Greed
Greed 's health after template 's attack is 1000

これはpythonが常に行うことですか、それとも私が何か間違ったことをしているのでしょうか。これらを呼び出されたくないからです(正しい用語を使用しなかった場合は申し訳ありませんが、私はちょっと新しいです)

4

4 に答える 4

5

ここで関数を呼び出しています:

slashp=attack("slash",1,2,5,player,boss)
slashb=attack("slash",1,2,5,boss,player)
kick=attack("kick",1,1,1,player,boss)

関数ではなく、そこに戻り値を格納しています。

いくつかの事前定義された引数を保存したい場合は、別の関数を使用して呼び出しをラップするか、ラムダ (基本的には関数を作成する簡略化された形式) を使用するか、または を使用functools.partial()していくつかの引数を事前定義し、それらの新しい callable を保存します。

ラムダを使用すると、次のようになります。

shlashp = lambda player, boss: attack("slash", 1, 2, 5, player, boss)
shlashb = lambda player, boss: attack("slash", 1, 2, 5, boss, player)
kick = lambda player, boss: attack("kick", 1, 1, 1, player, boss)

これは、後でこれらの関数を呼び出すときに、プレーヤーとボスを指定する必要があることを前提としています。kick(player, boss)たとえば、 を呼び出します。

との引数を交換しているため、使用functools.partial()はここでは適していません。変数を定義して、引数と引数を正しい順序で渡すだけです。bossplayerslashbossplayer

from functools import partial

slash = partial(attack, 'slash', 1, 2, 5)
kick = partial(attack, 'kick', 1, 1, 1)

またはのいずれslashかを呼び出すと、余分な引数kick追加さslash(player, boss)れるため、これらの 2 つの引数を既に定義した引数に追加して関数を呼び出します。

これらはすべて、複数のプレイヤーとボスを管理できるようにしたいという前提に基づいています。playerおよび変数がグローバルである場合(おそらく、戦うプレイヤーとボスは1 人しかbossいない可能性があります)、またはを定義するときにそれらを渡すだけで、追加の引数は渡されません。例えば:lambdapartial

slashp = partial(attack, 'slash', 1, 2, 5, player, boss)
slashb = partial(attack, 'slash', 1, 2, 5, boss, player)
kick = partial(attack, 'kick', 1, 1, 1, player, boss)

プレイヤーにボスを蹴らせるには、 を呼び出すだけkick()です。

partialオブジェクトとの違いは、オブジェクトを内省lambdaできることです。常に渡すように定義した引数を簡単に確認できます。partial

>>> from functools import partial
>>> def attack(*args): return args
...
>>> demo = partial(attack, 'kick', 1, 2, 5)
>>> demo.args
('kick', 1, 2, 5)
>>> demo()
('kick', 1, 2, 5)
>>> demo('player1', 'boss2')
('kick', 1, 2, 5, 'player1', 'boss2')

オブジェクトはクラスのpartialメソッドとして使用できませんが、関数オブジェクトは使用できます。クラスでこの機能を使用する必要がある場合は、functools.partialmethod()オブジェクトを使用してください。

于 2015-12-17T13:28:04.690 に答える
1

これがfunctools.partial目的です。

呼び出されたときに、位置引数 args およびキーワード引数 keyword で呼び出された func のように動作する新しい部分オブジェクトを返します。呼び出しにさらに引数が指定された場合、それらは args に追加されます。追加のキーワード引数が指定されている場合、それらはキーワードを拡張してオーバーライドします。

https://docs.python.org/2/library/functools.html#functools.partial

使用例:

import functools
slashp = functools.partial("slash",1,2,5,player,boss)
slashp()  # actual call 
于 2015-12-17T13:33:47.123 に答える
0

関数をラムダにラップします。

slashp=lambda : attack("slash",1,2,5,player,boss)

または部分的に使用します:

slashp=partial(attack, name="slash",minmultiplier=1,maxmultiplier=2,critchance=5,attacker=player,attackee=boss)
于 2015-12-17T13:28:00.233 に答える
0

クラスの方が適しているように見え、将来的にはより柔軟になります

class AttackType(object):
    def __init__(name, minmult, maxmult, crit):
        self.name = name
        self.minmult = minmult
        self.maxmult = maxmult
        self.crit = crit
    def attack(self, attackee, attacker):
        // all your logic here

kick = AttackType("kick", 1, 1, 1)
##... later
kick(player, boss)
于 2015-12-17T13:34:49.080 に答える