【问题标题】:Questions related to classes与课程相关的问题
【发布时间】:2017-12-24 13:21:33
【问题描述】:

在以下代码中,我在理解 Python 中数据结构的一些概念时遇到了问题。

class Stack(object):                        #1
    def __init__(self):                     #2
        self.items=[] 

    def isEmpty(self):
         return self.items ==[]

    def push(self,item):
        self.items.append(item)

    def pop(self):
        self.items.pop()

    def peak(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

s = Stack()
s.push(3)
s.push(7)

print(s.peak())
print (s.size())
s.pop()
print (s.size())

print (s.isEmpty())
    1. 我不明白这是什么object 参数
    2. 我将其替换为(obj) 并产生了错误,为什么?
    3. 我尝试将其删除,但效果很好,为什么?
    1. 为什么我有__init__ 来设置构造函数?
    2. self 是一个参数,但它是如何通过的呢?它代表哪个对象,它自己的类?

谢谢。

【问题讨论】:

  • 你应该在这里阅读文档:docs.python.org/3.6/tutorial/classes.html
  • 您的问题都是关于 Python 类的,而不是专门针对 Stack 的——也许您应该更改标题以反映这一点。
  • 谢谢你们的指导。
  • 我阅读了“Python 3 面向对象编程”这本书的前 3 章,我发现它比目前的文档更有帮助,我会向任何与这个主题有困难的人推荐它。再次感谢大家的指导。

标签: python stack


【解决方案1】:
  1. object 是一个类,Stack 继承自该类。没有 类obj,因此出错。但是,您可以定义一个类 不继承任何东西(至少在 Python 2 中)。
  2. self 表示调用方法的对象;为了 例如当你做s.pop()self里面的方法pop是指 与s 相同的对象 - 它不是类,它是类的实例

【讨论】:

    【解决方案2】:

    1

    object 这里是你的新类继承的类。已经有一个名为 object 的基类,但没有名为 obj 的类,这就是为什么用 obj 替换 object 会导致错误。无论如何,在您的示例代码中根本不需要它,因为 python 3 中的所有类都隐式扩展了对象类。

    2

    __init__ 是对象的构造函数,其中的 self 表示您正在创建的对象本身,而不是类,就像在您创建的其他方法中一样。

    【讨论】:

      【解决方案3】:

      第 1 点:

      这里需要一些历史...最初 Python 有两种不同的类型,一种是在 C 中实现的(无论是在 stdlib 还是在 C 扩展中),另一种是在 Python 中使用class 语句实现的。 Python 2.2 introduced a new object model(称为“新式类”)统一了两者,但保留了“经典”(又名“旧式”)模型以实现兼容性。这个新模型还引入了很多好东西,比如对计算属性的支持、通过super() 对象的协作超级调用、元类等,所有这些都来自内置的object 基类。

      因此,在 Python 2.2.x 到 2.7.x 中,您可以通过继承自 object(或 object 的任何子类)创建新式类,也可以不继承自 @987654329 创建旧式类@(也不是 - 显然 - object 的任何子类)。

      在 Python 2.7 中,由于您的示例 Stack 类不使用新对象模型的任何功能,因此它与“旧样式”或“新样式”类一样有效,但请尝试添加自定义元类或计算属性,它会以一种或另一种方式中断。

      Python 3 完全删除了旧式类的支持,如果您没有明确指定一个,object 是默认基类,因此无论您做什么,您的类都将继承自 object,并且无论有没有明确的父类都可以正常工作类。

      您可以read this了解更多详情。

      第 2.1 点 - 我不确定我是否真正理解了这个问题,但无论如何:

      在 Python 中,对象不是具有一组固定属性的固定的类似 C 结构的结构,而是类似 dict 的映射(当然也有例外,但我们暂时忽略它们)。对象的属性集由在类的所有实例之间共享的类属性(主要是方法,但实际上是在类级别定义的任何名称)和存储在实例的__dict__。这意味着您没有定义在类级别设置的实例属性(如在 Java 或 C++ 等中),而是在实例本身上设置它们。

      __init__ 方法在那里,因此您可以确保每个实例都使用所需的属性集进行初始化。它类似于 Java 构造函数,但它不仅用于在实例化时传递参数,还负责为您的类定义一组实例属性(在 Java 中,您可以在类级别定义)。

      第 2.2 点:self 是类的当前实例(调用方法的实例),因此如果 s 是您的 Stack 类的实例,s.push(42) 相当于 @987654340 @。

      请注意,参数不必称为self(这只是一个约定,尽管它是一个非常强大的约定),重要的是它是第一个参数。

      在调用s.push(42) 时,s 如何作为self 传递一开始有点复杂,但这是一个有趣的例子,说明了如何使用小功能集构建更大的功能集。你可以找到detailed explanation of the whole mechanism here,所以我不会费心在这里转发它。

      【讨论】:

      • 感谢您讲述这段历史 :)
      • 我尝试用任何东西替换“self”,它成功了。只是新的,这是一种常见的做法。谢谢。
      • 但是,知道 Python 采用这种新方式的原因吗?
      • @AhmedAbdelKhalek 第一点是有一个统一的对象模型,python 类可以从内置类型继承,第二点是向对象模型添加许多强大的功能——元类和描述符是最明显的。
      • 啊,太好了。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      • 2014-09-29
      • 2011-09-16
      相关资源
      最近更新 更多