【问题标题】:Using class instance as a function argument使用类实例作为函数参数
【发布时间】:2014-11-27 01:08:07
【问题描述】:

假设我有类似的东西:

class Dog:
   name = ""
   weight = 0
   def __init__(self,name,wg):
       self.name = name
       self.wg = wg

def feed(pet):
   pet.weight = pet.weight + 5
   if pet.weight > 20:
       print("your dog would get too fat")
   else:
       print("it is safe to feed your dog")

my_dog = Dog("sparky",10)
feed(my_dog)

有没有办法让对 pet.weight 的更改不会转移到 my_dog.weight?

我希望函数能够从类实例中获取信息,执行计算,然后保持原始实例不变。

【问题讨论】:

    标签: python function class arguments


    【解决方案1】:

    您正在重新分配此行上pet.weight 属性的值:

    pet.weight = pet.weight + 5
    

    即使在代码从feed 函数返回之后,这样做也会影响pet 实例。

    要解决此问题,只需创建一个等于 pet.weight + 5 的本地名称并改为使用它:

    def feed(pet):
       weight = pet.weight + 5
       if weight > 20:
           print("your dog would get too fat")
       else:
           print("it is safe to feed your dog")
    

    现在,我们使用pet.weight 的值,但不要更改它。


    另外,你错误地定义了你的类。通过这样做:

    class Dog:
       name = ""
       weight = 0
    

    您已将nameweight 设为Dog类属性。这意味着它们的值将在Dog 的所有实例之间共享,并且修改它们将影响所有实例。换句话说,您所有的Dogs 都将具有相同的名称和权重。

    但是你这样做了:

    def __init__(self,name,wg):
        self.name = name
    

    用同名的实例属性掩盖了类属性name。与类属性不同,实例属性对于类的每个实例都是唯一的。所以,weight 仍然是一个类属性(所有Dogs 共享),而name 现在是一个实例属性(每个Dog 唯一)。

    我认为最好删除这些行并像这样编写Dog 类:

    class Dog:
       def __init__(self, name, weight):
           self.name = name
           self.weight = weight
    

    现在,nameweight 都是实例属性。每个Dog 都有一个唯一的名称和权重,更改其中一个Dog 上的任何一个值将不再影响另一个Dogs。

    有关这方面的更多信息,您可以查看以下来源:

    【讨论】:

    • 其实他的属性在实践中是不会共享的,因为他在__init__中赋值。这将创建隐藏类属性的实例属性。但是,您是对的,最好删除类属性,因为如果删除实例属性(或者如果可变类属性发生突变而不是重新分配),这可能会导致混淆的属性共享行为。
    • 对,我已经澄清了。我认为 OP 可能认为他需要预先分配 nameweight 属性,然后再将它们分配到 __init__
    猜你喜欢
    • 2013-07-12
    • 1970-01-01
    • 2011-03-29
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多