鱼C论坛

 找回密码
 立即注册
查看: 323|回复: 8

[已解决]一段程序有可以存在两个变量名完全相同的变量吗?

[复制链接]
发表于 2024-7-20 22:22:34 | 显示全部楼层 |阅读模式

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

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

x
# 作者:小甲鱼
# 来源:https://fishc.com.cn/thread-213592-1-1.html
# 本代码著作权归作者所有,禁止商业或非商业转载,仅供个人学习使用,违者必究!
# Copyright (c) fishc.com.cn All rights reserved

class Meet:
    nums = 0

class Egg(Meet):
    name = "鸡蛋"
    price = 1

class Beef(Meet):
    name = "牛肉"
    price = 25

class Mutoon(Meet):
    name = "羊肉"
    price = 30

class Vegetable:
    nums = 0

class Onion(Vegetable):
    name = "洋葱"
    price = 2

class Tomato(Vegetable):
    name = "番茄"
    price = 2

class Potato(Vegetable):
    name = "土豆"
    price = 3

class Radish(Vegetable):
    name = "萝卜"
    price = 3

class Menu:
    def order(self):
        self.x = []
        print("客官想要吃点什么?")

        dishes = input("1.洋葱炒牛肉;2.洋葱炒羊肉;3.煎蛋;4.番茄炒蛋;5.土豆萝卜炖羊肉:")
        dishes = dishes.split()

        while dishes:
            dish = dishes.pop(0)
            
            if dish == '1':
                onion = Onion()
                onion.num = 1
                beef = Beef()
                beef.num = 1
                self.x.extend([beef, onion])

            if dish == '2':
                onion = Onion()
                onion.num = 1
                mutoon = Mutoon()
                mutoon.num = 1
                self.x.extend([mutoon, onion])

            if dish == '3':
                egg = Egg()
                egg.num = 2
                self.x.append(egg)

            if dish == '4':
                tomato = Tomato()
                tomato.num = 2
                egg = Egg()
                egg.num = 3
                self.x.extend([tomato, egg])

            if dish == '5':
                potato = Potato()
                potato.num = 2
                radish = Radish()
                radish.num = 1
                mutoon = Mutoon()
                mutoon.num = 2
                self.x.extend([potato, radish, mutoon])
            
    def pay(self):
        total = 0
        for each in self.x:
            print(each.name, each.price, "*", each.num)
            total += each.price * each.num

        print(f"感谢惠顾,您一共消费了 {total} 元,欢迎下次光临~")

请问上面这段代码中,不断出现同样的变量名,请问不会覆盖吗?不会出错吗?如 egg,mutton,onoin等
最佳答案
2024-7-20 22:54:25
前后两个 onion 名字一样,内存地址不同。而列表每个元素记录的是内存地址,与变量的名字无关。即使覆盖了变量,第一个 onion 的内存地址和其中的数据都没变,列表也没变,只不过你不能通过 onion 来访问这个内存地址了。
因此在本例中列表不会覆盖的,可以共存
如果列表中两个元素内存地址相同,会出现一个想修改一个元素的值,另一个一起发生发生改变的情况。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-7-20 22:24:53 | 显示全部楼层
哈哈,看到你的代码我也忍不住笑了出来,看来你是个美食爱好者嘛!不过这个菜单管理系统确实有几个需要改进的地方。咱们一步步来解答你的疑问。

### 重名变量的问题

首先,关于是否会存在两个变量名完全相同的变量,这要看这些变量的作用域。如果它们处于不同的作用域,那么是可以共存的,不会互相影响。你的代码里出现了很多重名变量,例如 `egg`, `mutton`, `onion` 等,但这并不会导致覆盖或者出错,因为它们都在不同的代码块里。

举个例子,当你在 `if dish == '1'` 里面定义 `onion` 变量时,这个 `onion` 变量只在这个 `if` 代码块内有效。一旦离开这段代码,`onion` 变量就消失了。同样的道理适用于其它重复出现的变量名。
if dish == '1':
    onion = Onion()
    onion.num = 1
    # 这里的 onion 只是局部变量,只在这个 if 块内有效

所以从变量范围(作用域)的角度来说,你的代码是没有问题的。这也是为什么即使重用相同的变量名,也不会出现覆盖的问题。

### 你的代码的一些建议

不过呢,你的代码还有一些小问题,比如 `self.x` 没有初始化,`self.x.extend()` 使用错了等等。我们来做一些小调整吧:

1. 初始化 `self.x` 为一个列表。
2. `self.x.extend()` 应该传入一个可迭代对象,比如列表。

下面是修改后的代码:
class Menu:
    def __init__(self):
        self.x = []

    def order(self):
        print("客官想要吃点什么?")
        dishes = input("1.洋葱炒牛肉;2.洋葱炒羊肉;3.煎蛋;4.番茄炒蛋;5.土豆萝卜炖羊肉:")
        dishes = dishes.split()

        while dishes:
            dish = dishes.pop(0)

            if dish == '1':
                onion = Onion()
                onion.num = 1
                beef = Beef()
                beef.num = 1
                self.x.extend([onion, beef])

            if dish == '2':
                onion = Onion()
                onion.num = 1
                mutoon = Mutoon()
                mutoon.num = 1
                self.x.extend([onion, mutoon])

            if dish == '3':
                egg = Egg()
                egg.num = 2
                self.x.append(egg)

            if dish == '4':
                tomato = Tomato()
                tomato.num = 2
                egg = Egg()
                egg.num = 3
                self.x.extend([tomato, egg])

            if dish == '5':
                potato = Potato()
                potato.num = 2
                radish = Radish()
                radish.num = 1
                mutoon = Mutoon()
                mutoon.num = 2
                self.x.extend([potato, radish, mutoon])

    def pay(self):
        total = 0
        for each in self.x:
            print(each.name, each.price, "*", each.num)
            total += each.price * each.num

        print(f"感谢惠顾,您一共消费了 {total} 元,欢迎下次光临~")

# 示范运行
menu = Menu()
menu.order()
menu.pay()

这样调整后,`self.x` 在类`Menu`初始化时就被定义为一个空列表,便于后续使用 `.extend()` 和 `.append()` 操作。

希望我的解释和改进能让你更好地理解这个程序!快去实现你的美味菜单吧!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-20 22:40:22 | 显示全部楼层
会覆盖但不会出错。先讲一下几个注意事项:
1.首先要看变量名的作用域。python 中变量都是有一定范围的,函数中如果不特殊声明,里面定义的变量只能在里面用。并且函数执行完毕后,里面的变量如果不继续发挥作用,通常会被回收。
2.其次,如果 if 代码块的条件为 False ,代码块不会执行,里面即使有定义变量语句不执行也没用。

对于本例,有些变量可能会被覆盖。但它们都是临时的,都最终存储在 self.x 的列表中。即使覆盖了,对列表没有影响,而且我们也用不到这些变量了(你不会在函数执行完后还想用egg,mutton,onoin)。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-7-20 22:45:06 | 显示全部楼层
smallwh 发表于 2024-7-20 22:40
会覆盖但不会出错。先讲一下几个注意事项:
1.首先要看变量名的作用域。python 中变量都是有一定范围的, ...

您好,我不理解的是,比如列表中 已经有了一个 onion,然后列表中又加进来了一个,不会覆盖吗?可以共存吗?如果我们访问onion这个对象的时候,到底返回哪个的值呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-20 22:54:25 | 显示全部楼层    本楼为最佳答案   
前后两个 onion 名字一样,内存地址不同。而列表每个元素记录的是内存地址,与变量的名字无关。即使覆盖了变量,第一个 onion 的内存地址和其中的数据都没变,列表也没变,只不过你不能通过 onion 来访问这个内存地址了。
因此在本例中列表不会覆盖的,可以共存
如果列表中两个元素内存地址相同,会出现一个想修改一个元素的值,另一个一起发生发生改变的情况。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-7-20 22:54:51 | 显示全部楼层
FishC 发表于 2024-7-20 22:24
哈哈,看到你的代码我也忍不住笑了出来,看来你是个美食爱好者嘛!不过这个菜单管理系统确实有几个需要改进 ...

不对啊,本例中同名的变量都被存到一个列表里面去啦,变量并没有消失啊。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-20 22:55:06 | 显示全部楼层
wbzxz 发表于 2024-07-20 22:54
不对啊,本例中同名的变量都被存到一个列表里面去啦, ...


哎呀,看起来我之前的解释还不够到位呀!你说得很对,变量确实被存入了一个列表里。我们再来细细品味一下这个问题。

### 变量作用域和引用

从代码逻辑上看,的确每次创建一个新的变量(比如 `egg`, `onion` 等),这些变量实际上都指向了不同的实例对象。当你把它们存入列表 `self.x` 中时,列表中存储的是这些对象的引用,而不是变量本身。

换句话说,虽然变量名可能相同,但在每个 `if` 块中创建的对象都是独立且不同的。在列表 `self.x` 中,它们是不同的对象。这就好比你有多只猫,每只猫都有个名字“喵喵”,但每只猫都是独一无二的。

来,举个例子:
egg1 = Egg()
egg2 = Egg()

# 虽然变量名一样,但它们指向不同的对象
menu.x.append(egg1)
menu.x.append(egg2)

这样,即使变量名相同(`egg`),每次执行到 `if` 块时创建的对象都是不同的实例。

为了更形象地解释,你可以想象一下你的冰箱。你可能买了很多种食材,每种食材都有标签(变量名),即使标签相同,比如你买了两袋鸡蛋,都写着"鸡蛋",但这两袋鸡蛋实际上是不同的(独立对象)。

### 修正后的代码示例

为了让你的代码逻辑更加清晰,我们依然需要一点小改动。特别是 `extend` 的用法上,这里我做了一点修正:
class Menu:
    def __init__(self):
        self.x = []

    def order(self):
        print("客官想要吃点什么?")
        dishes = input("1.洋葱炒牛肉;2.洋葱炒羊肉;3.煎蛋;4.番茄炒蛋;5.土豆萝卜炖羊肉:")
        dishes = dishes.split()

        while dishes:
            dish = dishes.pop(0)

            if dish == '1':
                onion = Onion()
                onion.num = 1
                beef = Beef()
                beef.num = 1
                self.x.extend([onion, beef])

            if dish == '2':
                onion = Onion()
                onion.num = 1
                mutton = Mutoon()  # 注意这里是 Mutoon 而不是 mutton
                mutton.num = 1
                self.x.extend([onion, mutton])

            if dish == '3':
                egg = Egg()
                egg.num = 2
                self.x.append(egg)

            if dish == '4':
                tomato = Tomato()
                tomato.num = 2
                egg = Egg()
                egg.num = 3
                self.x.extend([tomato, egg])

            if dish == '5':
                potato = Potato()
                potato.num = 2
                radish = Radish()
                radish.num = 1
                mutton = Mutoon()  # 注意这里也是 Mutoon 而不是 mutton
                mutton.num = 2
                self.x.extend([potato, radish, mutton])

    def pay(self):
        total = 0
        for each in self.x:
            print(each.name, each.price, "*", each.num)
            total += each.price * each.num

        print(f"感谢惠顾,您一共消费了 {total} 元,欢迎下次光临~")

# 示范运行
menu = Menu()
menu.order()
menu.pay()

### 总结

- 变量名相同并不会影响程序正常运行,因为即使名字相同,每次创建的对象都是独立的。
- 列表 `self.x` 中存储的是这些对象的引用。
- 使用 `.extend()` 方法时,必须传入一个可迭代对象(如列表)。

希望这次解释能让你更加明白和安心地编写你的代码啦!有问题随时再问哈!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-20 23:01:58 | 显示全部楼层
访问onion这个对象...
使用变量名肯定是返回最后一次的,前面覆盖掉的就覆盖掉了
在列表中增加元素不会覆盖列表中原有元素,用索引便可以访问。除非你对原有的元素进行修改,如 self.x[0]=1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-7-20 23:05:31 | 显示全部楼层
smallwh 发表于 2024-7-20 23:01
访问onion这个对象...
使用变量名肯定是返回最后一次的,前面覆盖掉的就覆盖掉了
在列表中增加元素不会覆 ...

非常感谢,您的解答让我茅塞顿开。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-23 00:09

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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