将self从一个成员函数传递给另一个类中的函数

huangapple go评论58阅读模式
英文:

Passing self from a member function to a function in another class

问题

为了上下文,我正在尝试在Python中实现一个极小化极大算法来玩井字游戏。以下是相关的代码:

TicTacToe.py

def dumbPlayer(game, gameType):
    return game.successors()[0]


class minimax:
    tree = None
    def minimaxPlayer(self, game, gameType):
        return game.successors()[0]


class TicTacToe:
    def play(self, xPlayer=consolePlayer, oPlayer=consolePlayer, output=consolePrint):
        while self.winner is None:
            output(self)
            if self.turn == 'X': self.move(xPlayer(self, TicTacToe))
            elif self.turn == 'O': self.move(oPlayer(self, TicTacToe))
        output(self, True)
        return

main.py:

import TicTacToe as TTT

player2 = TTT.minimax.minimaxPlayer
test = TTT.TicTacToe()

test.play(TTT.dumbPlayer, player2)

传递dumbPlayer函数是正常的,问题出在minimaxPlayer函数上。当play函数调用minimaxPlayer函数时,我收到以下错误:
TypeError: minimaxPlayer()缺少一个必需的位置参数:'gameType'

根据我对Python的理解,"self"参数会自动传递给函数,并且不能显式传递(或者可能不能显式传递)。所以在play函数看来,

def dumbPlayer(game, gameType)

def minimaxPlayer(self, game, gameType)

应该是等价的,但在这种情况下似乎不正确。

是否有一个简单的修复方法?还是我需要重新构建我的代码?如果必须的话,我已经有一些关于如何重构代码的想法,但我宁愿不这样做,并且我想知道为什么这不按照我期望的方式工作的根本原因。

英文:

For context, I am trying to implement a minimax algorithm in python to play tic tac toe. Here's the relevant code:

TicTacToe.py

def dumbPlayer(game, gameType):
    return game.successors()[0]


class minimax:
    tree = None
    def minimaxPlayer(self, game, gameType):
        return game.successors()[0]


class TicTacToe:
    def play(self, xPlayer=consolePlayer, oPlayer=consolePlayer, output=consolePrint):
        while self.winner is None:
            output(self)
            if self.turn == 'X': self.move(xPlayer(self, TicTacToe))
            elif self.turn == 'O': self.move(oPlayer(self, TicTacToe))
        output(self, True)
        return

main.py:

import TicTacToe as TTT

player2 = TTT.minimax.minimaxPlayer
test = TTT.TicTacToe()

test.play(TTT.dumbPlayer, player2)

Passing in the dumbPlayer function works fine, the problem comes with the minimaxPlayer function. When the play function calls the minimaxPlayer function, I get the following error:
TypeError: minimaxPlayer() missing 1 required positional argument: 'gameType'
From what I understand of python, the "self" parameter is automatically passed to the function and doesn't (or maybe can't) be passed explicitly, so as far as the play function is concerned,
def dumbPlayer(game, gameType) and
def minimaxPlayer(self, game, gameType)
should be equivalent, but it appears that's not correct in this case.

Is there an easy fix for this? Or will I need to refactor my code? I already have some ideas for how I can restructure the code if I have to, but I'd rather not, and I'd like to know the underlying reason for why this doesn't work how I expect.

答案1

得分: 1

对于实例方法的`self`参数会自动绑定到你从中获取该方法的实例上但你正在访问**的版本该方法

而不是

```python
player2 = TTT.minimax.minimaxPlayer

请执行以下操作:

minimax_instance = TTT.minimax()
player2 = minimax_instance.minimaxPlayer

它应该按照你的要求工作。

注意:在Python中的标准约定是使用CamelCase作为类名,使用snake_case作为实例名,这样就不需要使用像minimax_instance这样奇怪的名称来区分类和实例了。你可能还希望tree是一个实例属性,而不是一个类属性(如果想要能够将Minimax类与不同的游戏一起使用,你不希望不同的实例互相干扰状态)...

class Minimax:
    def __init__(self):
        self.tree = None

    def player(self, game, game_type):
        return game.successors()[0]
minimax = TTT.Minimax()
player2 = minimax.player

<details>
<summary>英文:</summary>

The `self` argument for an instance method is automatically bound to the instance that you got the method from, but you&#39;re accessing the *class*&#39;s version of that method.

Instead of:

player2 = TTT.minimax.minimaxPlayer


do:

minimax_instance = TTT.minimax()
player2 = minimax_instance.minimaxPlayer


and it should behave the way you want.

Note: the standard convention in Python is to use CamelCase for class names and snake_case for instance names, which eliminates the need to use weird names like `minimax_instance` to differentiate between the class and the instance.  You probably also want `tree` to be an instance attribute rather than a class attribute (if the idea is to be able to use the Minimax class with different games, you don&#39;t want the different instances stepping on each others&#39; state)...

class Minimax:
def init(self):
self.tree = None

def player(self, game, game_type):
    return game.successors()[0]

minimax = TTT.Minimax()
player2 = minimax.player




</details>



huangapple
  • 本文由 发表于 2023年6月2日 05:40:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定