Python 3中的类对象/实例是通过引用传递的吗?

时间:2012-11-21 07:02:06

标签: python python-3.x

此程序修改类“myclass”_x和_y的对象,但我不将其作为参数传递给函数try_block。如何修改对象?我是Python的新手。

class AddSub:
    def _init_(self): #how do default parameters work? 
        self._x, _y

    def set_x(self, num):
        self._x = num

    def set_y(self, num):
        self._y = num   

    def add(self):
        return self._x + self._y

    def sub(self):
        return self._x - self._y

def try_block():
    try:
        ch = int(input("type 1 to add, and 2 to subtract: "))

        myclass.set_x(int(input("enter an x value: "))) #how does myclass get modifed?

        myclass.set_y(int(input("enter a y value: ")))

        return ch

    except ValueError:
        print("Invalid entry.")

        ch = try_block()

        return ch


myclass = AddSub()

choice = try_block()

if choice == 1:
    print(myclass.add())

elif choice == 2:
    print(myclass.sub())

4 个答案:

答案 0 :(得分:7)

在我回答你的问题之前,我想提一些关于术语的事情。您的myclass值是一个实例,而不是一个类。您的代码中有一个名为AddSub的类。当您调用AddSub()时,您创建了该类的实例。对于这样的事情,学习正确的术语很重要,这样你就可以提出好的问题并理解你得到的答案。

您的代码接近工作,因为您正在将AddSub类的实例保存到名为myclass的全局变量中。稍后,您可以从try_block函数调用该全局变量的某些方法。这在Python中是合法的,但通常不推荐。

相反,您应该将对象作为参数传递:

def try_block(value):
    try:
        value.set_x(whatever())
    except ValueError:
        pass

您可以通过将AddSub类的实例传递给函数来调用它:

myAddSub = AddSub() # create the instance
try_block(myAddSub) # pass it to the function

这样更好,因为它不依赖于具有特定值的全局变量,如果需要,可以使用许多不同的AddSub实例调用它。

当前被破坏的代码的一部分是AddSub类的构造函数。没有必要声明变量。您可以随时分配给他们。如果您想设置默认值,也可以这样做:

def __init__(self):
    self._x = 0
    self._y = 0

如果您希望能够在构造对象时设置值,则可以向__init__方法添加其他参数。它们也可以有默认值,允许调用者省略其中的部分或全部:

def __init__(self, x=0, y=0):
    self._x = x
    self._y = y

根据该定义,所有这些都是构建AddSub实例的有效方法:

a = AddSub()     # gets default 0 value for both _x and _y
b = AddSub(5)    # gets default 0 value for _y
c = AddSub(y=5)  # gets default 0 value for _x
d = AddSub(2, 3) # no defaults!

最后一点主要与您的主要问题无关:您的try_block函数名称不佳,并且以比必要更复杂的方式实现。而不是递归,我认为它作为循环更有意义,就像在这个伪代码版本中一样:

def exception_prone_task():
    while True: # loops forever, or until a "return" or "break" statement happens
         try:
             result = do_stuff_that_might_raise_an_exception()
             return result # you only get here if no exception happened

         except WhateverExceptions as e:
             report_about_about_the_exceptions(e)

答案 1 :(得分:3)

简短回答:Python中的所有内容都是通过引用传递的。 (有些人喜欢添加“通过引用”)。

更长的答案是您的代码有点令人困惑。 (没问题,可以改进。)

首先,不应该以这种方式调用myclass,因为它不是类。它是AddSub类的一个实例 - 即该类的对象

其次,不应该为类提供动词的名称。它们应该是名词

每个类方法的第一个参数应该是self(为简单起见)。下一个参数是在创建类时传递的参数(即,当使用类名时,就像调用函数一样)。

每当你想给参数赋一个默认值时,你只需在参数后面写=value

作为未来对象一部分的方法定义中的所有内容都必须以self.为前缀(简化)。这样,您的__init__应如下所示:

    def _init_(self, x=1, y=2): #how do default parameters work? 
        self._x = x
        self._y = y

在我看来,对象变量使用_(下划线)前缀并不是必需的。

答案 2 :(得分:2)

myclass在模块顶层定义,因此可以作为全局变量访问。

答案 3 :(得分:-3)

Python中的所有内容都是一个对象。因此:参考