Python 我能';t在类外部获取已定义的变量以添加在类内部定义的变量

Python 我能';t在类外部获取已定义的变量以添加在类内部定义的变量,python,class,Python,Class,我不久前发布了这个,但我已经清理了一点,从那以后,问题仍然存在,因为没有人真正给出正确的答案。 所以我的问题是,我在类外定义的变量和循环stonepile和woodpile(在类内)没有多次向自身添加stone/wood(也在同一类内),我知道这一点,因为我得到了要打印的stonepile/woodpile。我已经测试过,问题实际上是开始时的stonepile/woodpile,每次被告知将stone/wood添加到stonepile/中时都会重置。我知道这一点,因为我和他们一起做过: y =

我不久前发布了这个,但我已经清理了一点,从那以后,问题仍然存在,因为没有人真正给出正确的答案。 所以我的问题是,我在类外定义的变量和循环
stonepile
woodpile
(在类内)没有多次向自身添加
stone
/
wood
(也在同一类内),我知道这一点,因为我得到了要打印的
stonepile
/
woodpile
。我已经测试过,问题实际上是开始时的
stonepile
/
woodpile
,每次被告知将
stone
/
wood
添加到
stonepile
/
中时都会重置。我知道这一点,因为我和他们一起做过:

y = random.randint(1,5)
x = random.randint(1,5)
woodpile = y
stonepile = x
结果是,如果开采的石头是1,x的randint是5,它将打印6。或者类似的东西。 有没有办法解决这个问题

整个代码如下:

import random
import time
idle = True
woodpile = 0
stonepile = 0

while True:
    class Taskassigner:
        def __init__(self,tasknum,stonepile,woodpile):
            self.tasknum = tasknum
            self.woodpile = woodpile
            self.stonepile = stonepile
        def choosejob(self,stonepile,woodpile):
            if self.tasknum == 1:
                self.chop(woodpile)
            if self.tasknum == 2:
                self.mine(stonepile)
        def chop(self,woodpile):
            wood = random.randint(1, 10)
            print('chopping wood')
            time.sleep(1.5)
            print('you got', wood)
            woodpile += wood
            print(woodpile)
            time.sleep(0.75)
        def mine(self,stonepile):
            stone = random.randint(1, 10)
            print('mining for stone')
            time.sleep(1.5)
            print('you got', stone)
            stonepile += stone
            print(stonepile)
            time.sleep(0.75)

    while idle:
        taskchance = random.randint(0,1)
        if taskchance == 1:
            tasknum = random.randint(0,2)
            job = Taskassigner(tasknum,stonepile,woodpile)
            job.choosejob(stonepile,woodpile)
            print
        else:
            print('idle')
            time.sleep(0.5)

如果要修改函数(或类函数)中的全局变量,则需要使用全局变量

foo = 0
def afunc():
    global foo
    foo = 1

afunc()
print foo

全局变量的名称与类内部的名称相同。我注意到一些地方,当您可能想要
self.woodpile+=wood
时,您在那里执行了
woodpile+=wood
,您可以找到一种方法,在
循环空闲时在
外部实例化变量。我会尝试不将tasknum作为
\uuuuu init\uuuu
输入变量之一

class Taskassigner:
        def __init__(self,stonepile,woodpile):
            self.tasknum = 0
            self.woodpile = woodpile
            self.stonepile = stonepile
此外,由于你不能砍石头或矿山木材,你不必把他们包括在你的所有方法。 i、 e

然后你可以打电话:

job = Taskassigner(tasknum,stonepile,woodpile)

while idle:
        taskchance = random.randint(0,1)
        if taskchance == 1:
            job.tasknum = random.randint(0,2)
            job.choosejob()
            print
        else:
            print('idle')
            time.sleep
            (0.5)

以下是我的工作代码的外观:

import random
import time
idle = True
woodpile=0
stonepile=0


class Taskassigner:
    def __init__(self,tasknum):

        self.tasknum = tasknum
        self.choosejob(tasknum)
    def choosejob(self,tasknum):

        if self.tasknum == 1:
            self.chop()
        if self.tasknum == 2:
            self.mine()
    def chop(self):

        global woodpile
        wood = random.randint(1, 10)
        print('chopping wood')
        time.sleep(1.5)
        print('you got', wood)
        woodpile += wood
        print(woodpile)
        time.sleep(0.75)
    def mine(self):

        global stonepile
        stone = random.randint(1, 10)
        print('mining for stone')
        time.sleep(1.5)
        print('you got', stone)
        stonepile += stone
        print(stonepile)
        time.sleep(0.75)


while idle:

    taskchance = random.randint(0,1)
    if taskchance == 1:
        tasknum = random.randint(0,2)
        Taskassigner(tasknum)
    else:
        print('idle')
        time.sleep(0.5)

以下是我认为您正在尝试的:

woodpile = 0
stonepile = 0

some_task = TaskAssigner(...)
some_task.chop()

woodpile == 3  # True
你真的不想这样。您永远不希望您的方法或函数影响未显式传递的内容,因为这会使调试非常困难。相反,您应该做如下操作:

class Stockpile(object):
    def __init__(self, starting_wood=0, starting_stone=0):
        self.woodpile = starting_wood
        self.stonepile = starting_stone

class TaskAssigner(object):
    def __init__(self, stockpile):
        self.stockpile = stockpile

    def mine(self):
        quantity = random.randint(1,5)
        self.stockpile.stonepile += quantity

    def chop(self):
        quantity = random.randint(1,5)
        self.stockpile.woodpile += quantity

    def do_task(self):
        if random.randint(0, 1):  # 50% chance
            random.choice([self.mine, self.chop])()
            # do either self.mine or self.chop

stockpile = Stockpile()

taskmaster = TaskAssigner(stockpile)

while True:
    if idle:
        taskmaster.do_task()
from types import MethodType
import random

class TaskAssigner(object):
    def __init__(self, stockpile):
        self.stockpile = stockpile
        self.tasks = []

    def make_task(self, attr_to_change, delta_min, delta_max, f_name):
        def f(self):
            qty = random.randint(delta_min, delta_max)
            new_total = getattr(self.stockpile, attr_to_change) + qty
            setattr(self.stockpile, attr_to_change, new_total)
        f.__name__ = f_name
        f = MethodType(f, self)
        setattr(self, f_name, f)
        self.tasks.append(f)

    def do_task(self):
        if random.randint(0, 1):
            random.choice(self.tasks)()
您可以通过执行以下操作使其更加模块化:

class Stockpile(object):
    def __init__(self, starting_wood=0, starting_stone=0):
        self.woodpile = starting_wood
        self.stonepile = starting_stone

class TaskAssigner(object):
    def __init__(self, stockpile):
        self.stockpile = stockpile

    def mine(self):
        quantity = random.randint(1,5)
        self.stockpile.stonepile += quantity

    def chop(self):
        quantity = random.randint(1,5)
        self.stockpile.woodpile += quantity

    def do_task(self):
        if random.randint(0, 1):  # 50% chance
            random.choice([self.mine, self.chop])()
            # do either self.mine or self.chop

stockpile = Stockpile()

taskmaster = TaskAssigner(stockpile)

while True:
    if idle:
        taskmaster.do_task()
from types import MethodType
import random

class TaskAssigner(object):
    def __init__(self, stockpile):
        self.stockpile = stockpile
        self.tasks = []

    def make_task(self, attr_to_change, delta_min, delta_max, f_name):
        def f(self):
            qty = random.randint(delta_min, delta_max)
            new_total = getattr(self.stockpile, attr_to_change) + qty
            setattr(self.stockpile, attr_to_change, new_total)
        f.__name__ = f_name
        f = MethodType(f, self)
        setattr(self, f_name, f)
        self.tasks.append(f)

    def do_task(self):
        if random.randint(0, 1):
            random.choice(self.tasks)()
然后你可以做:

class Stockpile(object):
    def __init__(self, starting_wood=0, starting_stone=0, starting_grain=0):
        self.woodpile = starting_wood
        self.stonepile = starting_stone
        self.grainsilo = starting_grain

stockpile = Stockpile()
tasks = TaskAssigner(stockpile)

tasks.make_task('woodpile', 1, 5, 'chop_wood')
tasks.make_task('stonepile', 1, 5, 'mine_stone')
tasks.make_task('grainsilo', 2, 10, 'harvest_grain')

tasks.harvest_grain()  # adds to stockpile.grain_silo!
tasks.do_task()  # 50% does nothing, 50% does one of the three!

但是请注意,这是非常高级的,除非您深入理解它,否则我强烈建议您此时不要尝试这种元编程

为什么您的类定义在循环中?在
\uuuu init\uuuu()
中,您连续分配
self.woodpile
两次,为什么?我修复了它,但它仍然没有做我想让它做的事嘿@FlyingNat,是我回答了你的问题。我留下了什么不清楚的地方?你好,我可能没有说清楚,我只是想让它工作起来,这样我知道我可以正确地编写代码,让它按照我想要的方式工作。我很抱歉,因为我觉得你不会喜欢我,因为我没有利用你的想法。我是青少年,请原谅我的语法和孩子气。如果你想知道我的问题,请阅读这个问题。谢谢你,我会改进我的编码,如果它有效,我会同意答案。再次感谢你。虽然这会起作用,但这是一个糟糕的设计选择。您应该尽可能避免
global
,因为它破坏了封装。它可以工作!!!谢谢你的帮助。我在类中使这两个变量都是全局的,但它得出了这样的结论:“SyntaxError:name'woodpile'是parameter and global.”所以我从类的所有参数中删除了这两个变量,现在它按照我希望的方式工作了。我将它修好了一点点,得到了这个结果:random.choice(self.my,self.chop)()TypeError:choice()接受2个位置参数,但有3个是given@FlyingNat哎呀,修好了。我总是认为
是随机的。choice
接受
*args
,但它实际上只接受一个选项列表。“object”是干什么的?顺便说一句,谢谢您的帮助!这次你帮了大忙。“对不起,我不是故意小气的。@FlyingNat你听起来不小气!”!问问题很好!应该回答为什么我使用
类名(对象)
而不是
类名
。这只是习惯,因为Python3默认使用新样式的类。这有什么问题吗?有什么我可以收紧的吗?请反馈我的工作代码