【问题标题】:Why do I have to set 'resizemode' to 'user' twice in order for my change to 'stretchfactor' to take effect when using 'turtle'?为什么我必须将 'resizemode' 设置为 'user' 两次才能让我对 'stretchfactor' 的更改在使用 'turtle' 时生效?
【发布时间】:2017-05-20 15:31:03
【问题描述】:

我正在使用 Python 3.6.0 自动化 Cracker Barrel 中的“三角钉游戏”,目前正在使用“turtle”实现其图形。我创建的两个类与此问题相关:“Game”(包含在主包的模块中)和“TurtleGraphics”(包含在子包“graphics”的模块中),其预期目的是自我解释性的。当以“TurtleGraphics”对象作为参数调用“Game”对象时,两个对象相互链接,并调用“graphics._construct()”,它定义了一个“Pen”对象并设置其“stretchfactor” '使用'pen()'。这就是问题所在。即使我在我的 'turtle.cfg' 文件中将 'resizemode' 设置为 'user',我必须再次将 'resizemode' 设置为 'user' 作为 'pen()' 的参数,以便构建图形从游戏中调用时正确。奇怪的是,如果我直接运行包含“TurtleGraphics”的模块并创建一个图形对象,它就可以正常工作。此外,即使我从游戏对象调用图形,使用 'shapesize()' 而不是 'pen()' 设置 'stretchfactor' 也有效。首先,我将发布 'Game.__call__' 和 'TurtleGraphics._construct' 的代码,在每个模块的导入前加上可能是相关的。我还将发布“TurtleGraphics.__init__”和“TurtleGraphics._draw_board”。 (这两个类都有基类,但 'BaseGame' 不处理图形,而 'Graphics' 是抽象的,因此在这种情况下它们无关紧要。另外,值得一提的是,'Game' 没有 '__init__' 方法. 所有实例属性都是在调用时分配的。)然后我将解释我迄今为止对此事所做的研究。

游戏.__call__:

from tripeg.graphics import Graphics
from tripeg.graphics.ascii_ import ASCIIGraphics
from tripeg.graphics.turtle_ import TurtleGraphics

#...

def __call__(self, graphics=None):
    """Starts the game with given graphics, or none, if not given."""
    super().__call__()
    if graphics:
        if not isinstance(graphics, Graphics):
            raise TypeError(f"Argument '{graphics}' is not of type"
                            " 'Graphics'.")
        else:
            self._graphics = graphics
            self._graphics._game = self
            self._graphics._construct()

TurtleGraphics._construct:

import os
import turtle
from turtle import Screen, RawPen, Pen, Shape, Terminator, _CFG

from tripeg.graphics import Graphics

#...

def __init__(self):
    """Initialize self. See help(type(self)) for accurate signature."""
    os.chdir("C:\\Users\\Sylvaenn\\Python3.6.0\\Programs\\tripeg\\graphics")
    turtle.readconfig("turtle.cfg")

#...

def _construct(self):
    """Constructs the graphics for the game."""
    self.window = Screen()
    self.window.setworldcoordinates(0,0,10,10)
    self._draw_board()

#...

def _draw_board(self):
    """Draws the game board."""
    wh_ratio = self.window.canvwidth / self.window.canvheight

    tri_board = Shape("compound")
    tri_board.addcomponent(((0,0),(8,0),(4,8)),(51,25,0),"black")
    self.window.addshape("tri_board", tri_board)

    board = Pen("tri_board")
    board.pen(pendown=False, outline=7, stretchfactor=(60*wh_ratio,60))
    import pdb; pdb.set_trace()
    board.setheading(90)
    board.goto(1,1)
    board.stamp()

现在,这是我迄今为止发现的:

我使用 'pdb' 创建了一个断点,并在调用 'pen()' 之后直接放置它。当我运行游戏模块并从游戏中调用图形时,就像这样......

>>> ga = Game()
>>> gr = TurtleGraphics()
>>> ga(gr)
> c:\users\sylvaenn\python3.6.0\programs\tripeg\graphics\turtle_.py(82)._draw_board()
-> board.setheading(90)
(Pdb) !board.pen()
{'shown': True, 'pendown': False, 'pencolor': 'black', 'fillcolor':   'black', 'pensize': 1, 'speed': 3, 'resizemode': 'noresize', 'stretchfactor': (71.46496815286623, 60), 'shearfactor': 0.0, 'outline': 7, 'tilt': 0.0}
(Pdb)

...'stretchfactor' 已更改,但尽管有 cfg 文件,'resizemode' 仍设置为 'noresize'。

如果我运行图形模块并直接调用图形,像这样......

>>> gr = TurtleGraphics()
>>> gr._construct()
> c:\users\sylvaenn\python3.6.0\programs\tripeg\graphics\turtle_.py(82)_draw_board()
-> board.setheading(90)
(Pdb) !board.pen
{'shown': False, 'pendown': False, 'pencolor': 'black', 'fillcolor': 'black', 'pensize': 1, 'speed': 3, 'resizemode': 'user', 'stretchfactor': (71.46496815286623, 60), 'shearfactor': 0.0, 'outline': 7, 'tilt': 0.0}
(Pdb) 

...'stretchfactor' 和 'resizemode' 都有预期的值。

我已经尝试过的:

  1. 分析了“turtle”的源代码,特别是“pen()”、“_CFG”以及“Turtle”、“RawTurtle”类及其基类
  2. 广泛阅读 python.org 上的教程和方法文档字符串
  3. 使用 IDLE 调试器和“pdb”逐步运行程序

正如我在开头所说的,我可以通过在 'pen()' 和 cfg 文件中包含“resizemode='user'” 或使用 'shapesize()' 来完成这项工作。只是我想知道为什么我的 cfg 文件在所有情况下都不能达到预期的目的,我想更好地理解 'turtle' 模块和 Python,如果我不明白为什么会发生这种情况,我'我确信我以后会遇到更严重的错误,而且我无法修复它们。

【问题讨论】:

  • 是的,我知道这篇文章很长,但我宁愿精确和冗长,也不愿模糊和简洁。
  • 精确并不一定意味着冗长。你为此付出了很多努力,我非常感谢你这样做。这使您与几乎不尝试的大量用户区分开来。但是,在这么长的帖子中,几乎可以肯定,您可以 1) 删除或 2) 在不需要理解问题的“背景”部分中隔离很多内容。相信我,我明白。很多草稿文本从未进入帖子的好问题并不少见。我认为如果您提供 less 上下文并更多地关注问题,这篇文章会做得更好。
  • 提出好的问题其实真的很难,而且是一项必须练习和掌握的技能。我可以告诉你有这样做的动力;你所要做的就是继续努力。 =) 请在您减少这个问题后给我留言以 ping 我;我想回来看看。
  • 非常感谢您的反馈。关于编程,我有“不要遗漏任何可能相关的东西”的心态不知何故钻进了我的脑海。我的文档也倾向于迂腐,这肯定比相反的要好,但我绝对可以改进。一旦我把它修剪下来,我一定会告诉你的。
  • 钻到你身上并不是一件完全坏事。最好在草稿阶段从太多开始,然后将其削减。您实际上需要在最后一篇文章中取得平衡:您希望包含足够的信息而不包含太多供读者处理的信息,不幸的是,有时甚至很难确切知道需要哪些信息(因为知道需要哪些信息需要知道可能的解决方案)。你会做得更好,通常,当你不太确定需要什么时,知道答案的人可以提出澄清问题。

标签: python python-3.x turtle-graphics


【解决方案1】:

我想知道为什么我的 cfg 文件在 所有情况

这是我对您的情况的分析。您的代码的关键是:

import turtle
#...
def __init__(self):
    os.chdir("C:\\Users\\Sylvaenn\\Python3.6.0\\Programs\\tripeg\\graphics")
    turtle.readconfig("turtle.cfg")

需要注意的两件事可能并不明显:

  1. turtle.readconfig() 的参数被忽略。相反,它看起来 对于目录中的硬编码文件名“turtle.cfg” *.py 源文件来自当前工作目录。在 那个命令。如果两者都加载,则第二个优先 存在。 (还有第三种可能的配置文件我就不去了 到这里。)

  2. 如果 os.chdir() 出现在 import turtle 之后,它看起来不会 对于刚刚更改到的目录中的配置文件。 如果您愿意,os.chdir() 必须在 import turtle 之前 它在 chdir'd 目录中查找。即使明确调用 turtle.readconfig()

为了演示第二点,首先在临时目录中创建一个配置文件:

mkdir temporary_directory
echo "resizemode = user" > temporary_directory/turtle.cfg

运行此代码:

import os
import turtle

from os.path import isfile

current_directory = os.getcwd()

os.chdir("temporary_directory")

turtle.readconfig(None)

print(turtle.resizemode())

您将获得默认的noresize 模式。使用此修改再次运行代码:

import os

from os.path import isfile

current_directory = os.getcwd()

os.chdir("temporary_directory")

import turtle

turtle.readconfig(None)

print(turtle.resizemode())

您将获得模式user

最后,如海龟文档中所述,resizemode('user') 在使用参数调用 shapesize() 时由 shapesize() 调用。

【讨论】:

  • 我得到的结果与您的答案不符,尽管从我阅读文档来看,我认为他们会。我尝试了你的测试代码,实际上我两次都得到了“noresize”。我在pdb 中运行了__init___CFG 用我的cfg 文件进行了更新。实际上,在发布此内容几个小时后,我的代码就可以工作了。当我写完这篇文章时,我将在一篇文章中解释它。不过,感谢您的反馈。至少,我了解到我可以将readconfig() 的参数更改为None,并且效果相同。
  • @IsaacSaffold,因为我使用的是 Unix,而你使用的是 Windows,并且涉及到 os 模块,所以我想你的结果不同并不会让我感到惊讶。我很高兴您的工作顺利进行,但我理解您的沮丧。
  • 它又以同样的方式搞砸了(我仍然不知道我是如何临时修复它的),我只是把os.chdir 放在import turtle 上面,它就起作用了。所以你毕竟是解决方案。我很感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 2014-02-15
相关资源
最近更新 更多