wbzxz 发表于 2024-7-20 22:22:34

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

# 作者:小甲鱼
# 来源: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()

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

            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()

            if dish == '5':
                potato = Potato()
                potato.num = 2
                radish = Radish()
                radish.num = 1
                mutoon = Mutoon()
                mutoon.num = 2
                self.x.extend()
            
    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等

FishC 发表于 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()

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

            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()

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

    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 小助理,如未能正确解答您的问题,请继续追问。

smallwh 发表于 2024-7-20 22:40:22

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

对于本例,有些变量可能会被覆盖。但它们都是临时的,都最终存储在 self.x 的列表中。即使覆盖了,对列表没有影响,而且我们也用不到这些变量了(你不会在函数执行完后还想用egg,mutton,onoin)。

wbzxz 发表于 2024-7-20 22:45:06

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

您好,我不理解的是,比如列表中 已经有了一个 onion,然后列表中又加进来了一个,不会覆盖吗?可以共存吗?如果我们访问onion这个对象的时候,到底返回哪个的值呢?

smallwh 发表于 2024-7-20 22:54:25

前后两个 onion 名字一样,内存地址不同。而列表每个元素记录的是内存地址,与变量的名字无关。即使覆盖了变量,第一个 onion 的内存地址和其中的数据都没变,列表也没变,只不过你不能通过 onion 来访问这个内存地址了。
因此在本例中列表不会覆盖的,可以共存
如果列表中两个元素内存地址相同,会出现一个想修改一个元素的值,另一个一起发生发生改变的情况。

wbzxz 发表于 2024-7-20 22:54:51

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

不对啊,本例中同名的变量都被存到一个列表里面去啦,变量并没有消失啊。

FishC 发表于 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()

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

            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()

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

    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 小助理,如未能正确解答您的问题,请继续追问。

smallwh 发表于 2024-7-20 23:01:58

访问onion这个对象...
使用变量名肯定是返回最后一次的,前面覆盖掉的就覆盖掉了
在列表中增加元素不会覆盖列表中原有元素,用索引便可以访问。除非你对原有的元素进行修改,如 self.x=1

wbzxz 发表于 2024-7-20 23:05:31

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

非常感谢,您的解答让我茅塞顿开。{:10_340:}
页: [1]
查看完整版本: 一段程序有可以存在两个变量名完全相同的变量吗?