鱼C论坛

 找回密码
 立即注册
查看: 2817|回复: 5

[已解决]类变量赋值相关问题

[复制链接]
发表于 2023-3-3 12:46:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
class aa:
    def __init__(self):
        self.s1 = None
        self.s2 = None

    def asa(self,bb):
        self.s1 = bb
        p = self.s1
        self.s2 = p
        return p
        
        #return self.s2
    def sadsa(self):
        self.s1.id = 3
class bb:
    def __init__(self):
        self.id = 0

    def setId(self,id):
        self.id = id

c = bb()
c.setId(2)
#print(c.id)
d = aa()
d.asa(c)
d.sadsa()
print(d.s2.id)
#print(d.asa(c).id)
#print(c.id)

求问,为啥打印出来得值是3,明明给s2赋值时候是2,之后只是s1变了,为啥s2的值跟着一起变了,怎么样使得s2不跟着一起变呢?即打印出来得值为2




#def reyu():
#    a = 1
#    b =2
#    return a,b
#
#c = reyu()
#print(c[1])
最佳答案
2023-3-3 13:51:35
kking1 发表于 2023-3-3 13:44
有没有类似赋值的功能而不是对相关对象的引用呢?赋值之后就静态不动了


在 Python 中,赋值过程中不明确区分拷贝和引用。

一般对静态变量的传递为拷贝,对动态变量的传递为引用。

你可以使用深拷贝来实现你想要的效果。
import copy                                                    # 引入 copy 模块
class aa:
    def __init__(self):
        self.s1 = None
        self.s2 = None

    def asa(self,bb):
        self.s1 = bb
        self.s2 = copy.deepcopy(bb)                             # 用深拷贝
        return self.s2
        
        #return self.s2
    def sadsa(self):
        self.s1.id = 3
class bb:
    def __init__(self):
        self.id = 0

    def setId(self,id):
        self.id = id

c = bb()
c.setId(2)
#print(c.id)
d = aa()
d.asa(c)
d.sadsa()
print(d.s2.id)
#print(d.asa(c).id)
#print(c.id)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-3-3 12:53:25 | 显示全部楼层
这是因为在 asa 方法中,self.s1 和 self.s2 都被赋值为指向同一个对象 bb 的引用。

所以当你在 sadsa 方法中更改了 self.s1.id 的值时,

由于 self.s1 和 self.s2 指向的是同一个对象,所以打印出来的值也会随之改变。

如果你想让打印出来的值为2,可以在给 self.s2 赋值时创建一个新的对象并将其属性设置为与原对象相同。

例如,在 asa 方法中,可以将代码更改为:
def asa(self, bb):
    self.s1 = bb
    p = bb.__class__()
    p.__dict__ = bb.__dict__.copy()
    self.s2 = p
    return p
这样,在调用 d.asa(c) 后,d.s2.id 的值就会保持不变。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-3 13:44:41 | 显示全部楼层
isdkz 发表于 2023-3-3 12:53
这是因为在 asa 方法中,self.s1 和 self.s2 都被赋值为指向同一个对象 bb 的引用。

所以当你在 sadsa  ...

有没有类似赋值的功能而不是对相关对象的引用呢?赋值之后就静态不动了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-3 13:51:35 | 显示全部楼层    本楼为最佳答案   
kking1 发表于 2023-3-3 13:44
有没有类似赋值的功能而不是对相关对象的引用呢?赋值之后就静态不动了


在 Python 中,赋值过程中不明确区分拷贝和引用。

一般对静态变量的传递为拷贝,对动态变量的传递为引用。

你可以使用深拷贝来实现你想要的效果。
import copy                                                    # 引入 copy 模块
class aa:
    def __init__(self):
        self.s1 = None
        self.s2 = None

    def asa(self,bb):
        self.s1 = bb
        self.s2 = copy.deepcopy(bb)                             # 用深拷贝
        return self.s2
        
        #return self.s2
    def sadsa(self):
        self.s1.id = 3
class bb:
    def __init__(self):
        self.id = 0

    def setId(self,id):
        self.id = id

c = bb()
c.setId(2)
#print(c.id)
d = aa()
d.asa(c)
d.sadsa()
print(d.s2.id)
#print(d.asa(c).id)
#print(c.id)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-3 15:27:09 | 显示全部楼层
isdkz 发表于 2023-3-3 13:51
在 Python 中,赋值过程中不明确区分拷贝和引用。

一般对静态变量的传递为拷贝,对动态变量的传递为 ...

这个深拷贝和你楼上那个方法有什么区别?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-3 17:25:38 | 显示全部楼层
本帖最后由 歌者文明清理员 于 2023-3-3 17:27 编辑
kking1 发表于 2023-3-3 15:27
这个深拷贝和你楼上那个方法有什么区别?


对普通元素来说没有区别,但是对可变对象来说不是
比如
lista = [[1, 2, 3], [7], 6]
listb = lista.copy()
listb[1][0] = 5
print(lista)
# [[1, 2, 3], [5], 6]
因为listb和lista虽然不是一个东西,但是他们的元素一样,是同一个东西
用deppcopy相当于会把[1, 2, 3]and [7]也拷贝一次
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-2 00:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表