【问题标题】:Accessing outer class from inner python从内部python访问外部类
【发布时间】:2013-03-05 22:40:30
【问题描述】:

考虑这段代码:

class Page(object):
  def __init__(self, name, title):
    self.name   = name
    self.title  = title
    self.selected = False
  def select(self):                 <-- How can I make this method work?
    for Page in Pages:
        Page.selected = False
    self.selected = True
class Website(object):
  def __init__(self):
    self.index    = Page("index", "Home")
    self.settings = Page("settings", "Settings")
    self.users    = Page("users", "Users")
    self.logs     = Page("logs", "Logs")
    self.faq      = Page("faq", "FAQ")
  def __iter__(self):
    return iter([self.index, self.settings, self.users, self.logs, self.faq])
Pages = Website()

我正在尝试做的事情似乎有点非法。不过,我确信有办法做到这一点。看来我可能不得不在某处重写 get 方法。非常感谢您的帮助!

这是我打算使用 Bottlepy 使用这些类的方式:

设置页面:

@route('/')
@route('/<selectedPage>')
@route('/<selectedPage>/')
def dynamic_routing(selectedPage='index'):
  for Page in Pages:
     if selectedPage == Page.name:
            Page.select()
  return template('default')

检索页面信息(在 Bottlepy 模板内):

%for Page in Pages:
    %if Page.selected:
        <title>{{Page.title}}</title>                
    %else:
        <title>Page Not Found</title>
    %end
%end

我现在将代码编辑为工作版本。谢谢大家这么快的输入!!!你们真棒!仍然可能不是最好的方法,但我现在想不出另一种方法来解决它。

【问题讨论】:

  • PEP-8 建议仅使用 CapWords 作为类名 - 它使代码更具可读性。同样,它建议不要排列作业。这里也没有外部类或内部类(尽管这些概念在 Python 中完全无关紧要)。
  • 它已经可以工作了,只需添加一个self 参数。
  • @MartijnPieters 它不会,你需要一个 Pages 的实例——你不能浏览整个类。
  • @Lattyware:他用 Pages 实例替换了 Pages 类。
  • @MartijnPieters 构造函数将在此之前运行。

标签: python class outer-join


【解决方案1】:

您需要重命名.select 属性或.select() 方法,并在方法中添加self 参数,否则您的代码将起作用:

class Page(object):
    def __init__(self, name, title):
        self.name   = name
        self.title  = title
        self.selected = False

    def select(self):
        for Page in Pages:
            Page.selected = False
        self.selected = True

通过这些更改,您的代码可以正常工作:

>>> Pages = Pages()
>>> Pages.index
<__main__.Page object at 0x10a0b6cd0>
>>> Pages.index.selected
False
>>> Pages.index.select()
>>> Pages.index.selected
True
>>> Pages.faq.select()
>>> Pages.index.selected
False

然而,这并不是说这是一个好的架构设计。我想说您需要将选择页面的责任转移到 Pages 类,最重要的是避免用全局实例 Pages 替换类 Pages

【讨论】:

  • 它唯一起作用,它出于某种原因选择了所有东西
  • 不,不是这个答案中的代码。查看演示会话; when faq is selected, .index.selected is False.
  • 使用我对Page的定义;其他一切都和以前一样。
  • 搞定了。我的代码很繁琐,所以花了一些时间来测试它。起初它不起作用,因为我忘记在我实际测试此条件的代码中的某个位置将 select 更改为 selected 。非常感谢!!!作为一个附带问题,解决此类问题的最佳方法是什么? (我在上面有更多详细信息)
【解决方案2】:

我认为这里最好的解决方案是将您的 select() 方法移动到 Pages 类:

class Pages(object):
    ...
    def select(self, target):
        for page in self:
           page.select = False
        target.select = True

对我来说,这似乎是一个更合乎逻辑的位置,这意味着 Page 实例不需要知道它们所属的 Pages 实例。

在保存所选页面的Pages 实例上简单地拥有一个selected 属性可能会更好,而不是每个Page 都知道它是否被选中,但这取决于设计。

【讨论】:

  • 我可以移动到页面,但是如何从单个页面触发这种方法?我不断收到 TypeError: 'bool' object is not callable error now
  • @user2137711 你没有。重组你的程序而不依赖它更有意义。
  • 所以我打算使用它的方式是这样的:
【解决方案3】:

一个 Pages 对象管理多个单独的 Page 对象。它应该负责将它们全部作为一个集合涉及的事情,例如,在您的示例中,将单个页面标记为选中并取消标记其他页面。

虽然您可以让每个 Page 了解拥有它的 Pages 对象,但这样做过多可能会很快导致乱七八糟的意大利面条代码。

附: - 试着想出一些更好的名字,即使谈论有 Page-s 和 Pages 也很不舒服。

【讨论】:

    【解决方案4】:

    将引用存储到pageset,然后循环浏览该集合中的页面

    class Page(object):
      def __init__(self, name, title, pageset):
        self.name   = name
        self.title  = title
        self.pageset = pageset
      def select(self):
        for page in self.pageset.pages:
            page.select = False
        self.select = True
    
    class Pageset(object):
      def __init__(self):
        self.index    = Page("index", "Home", self )
        self.settings    = Page("settings", "Settings", self )
        self.pages = [ self.index , self.settings , ]
    

    请注意,这使您能够拥有多个 Pagesets ,并且您正在查看类实例。您上面的代码引用了类本身(实际上没有理由这样做)。我将self.pages 作为属性,因为您可能希望将其他数据存储在页面集中。

    【讨论】:

    • self 方法的 self 参数在哪里?您正在使用同名属性隐藏方法。
    • 谢谢。我只是打字这么快。这是一个非常尴尬的问题。我有点想删除我的答案 - 因为问题本身似乎有点倒退。
    猜你喜欢
    • 2016-08-04
    • 2014-02-11
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2011-02-13
    相关资源
    最近更新 更多