gux 发表于 2021-1-29 16:31:14

关于 __init__ 的参数的默认值

本帖最后由 gux 于 2021-1-29 16:34 编辑

问题源于 零基础入门学习 Python 038节编程题 1。我试着定义了一个平面上的点的类 Point:

class Point:
    def __init__(self, cor = ):
      self.cor = cor # 平面上一点的坐标

编辑器建议我把代码改为

class Point:
    def __init__(self, cor = None):
      if cor is None:
            cor =
      self.cor = cor

这样改的好处是什么?

Twilight6 发表于 2021-1-29 16:31:15


因为你第一个代码 默认参数的值设置为一个列表,因为列表是可变的,会导致你列表中元素可能发生改变

举个例子,下面这个代码执行同个函数就会导致原本是默认的参数变成变化的参数:

def test(list1=[], number=100):
    list1.append(number)
    print(list1)
   
test()
test()
test()

输出结果,每次调用同个函数,默认参数的结果都不同:





kogawananari 发表于 2021-1-29 18:27:38

你的编辑器真高级啊{:10_292:}

Stubborn 发表于 2021-1-29 21:50:03

本帖最后由 Stubborn 于 2021-1-29 21:51 编辑

# -*- coding: utf-8 -*-
# !/usr/bin/python3
"""
@ version: ??
@ author: Alex
"""

def function(val, val_type=None):
    """
   如果默认值是 可变类型容器,例如 list,dict,set
      那么应该把默认值设置为None,其代码这样写。
    """

    # if not val_type: 应该使用is None , 避免其他的参数,如 0、空集合、空列表被当做False误判

    if val_type is None:
      val_type = []

_no_value = object()
def function_one(val, val_type=_no_value):
    """
    如果不打算提供一个默认值
      只想检测可选参数是否被赋予了特定的值,其代码这样写。
    """
    if val_type is _no_value: # Note that _no_value is a global variable
      print("No val_type value supplied")


对默认参数的赋值,只在函数定义的时候绑定一次,例如上面 function_one 的默认参数,在定义的时候 val_type 已经指向了 object 对象,对 _no_value 的值修改,影响不到 val_type ,只会影响 if 判断。所以给参数的默认是应该总是:不可变对象、比如True,False,字符串,数字。

Cool_Breeze 发表于 2021-1-30 11:27:14

什么编辑器,pycharm?

_2_ 发表于 2021-1-30 17:00:04

这样改的好处就是不会在初始化时给赋予一个无意义的值
如果凭这个类的意义的话其实 cor 只能为一个具有两个值的序列,但是编辑器并不知道,所以默认给了 None
把判断 cor 是否合法放在内部判断就可以避免许多不应有的 bug

Alwyn_Yin 发表于 2021-2-1 08:53:57

可能这样更好一点
def __init__(x,y):
        self.x = x,
        self.y = y

_2_ 发表于 2021-2-1 20:10:24

Alwyn_Yin 发表于 2021-2-1 08:53
可能这样更好一点
def __init__(x,y):
        self.x = x,


不太符合坐标系内任意点的定义吧
如果你这样只是描述了一个点的 x 轴和 y 轴的位置,并不完整
写成一个含有 2 个元素的序列似乎更好一点

gux 发表于 2021-2-4 00:19:41

Cool_Breeze 发表于 2021-1-30 11:27
什么编辑器,pycharm?

是的。

gux 发表于 2021-2-4 00:21:43

Stubborn 发表于 2021-1-29 21:50
对默认参数的赋值,只在函数定义的时候绑定一次,例如上面 function_one 的默认参数,在定义的时候 val ...

序列 是一个可变的对象吗?

Stubborn 发表于 2021-2-4 14:55:31

gux 发表于 2021-2-4 00:21
序列 是一个可变的对象吗?

列表属于可变对象,它是一个容器类,你往里面塞值,但是容器本身不会改变

°蓝鲤歌蓝 发表于 2021-2-7 18:32:44

就拿你这个例子来说,你测试一下下面的代码就明白会出什么问题了。
class Point:
    def __init__(self, cor=):
      self.cor = cor# 平面上一点的坐标


p1 = Point()
p1.cor.append(1)

p2 = Point()
print(p2.cor)
页: [1]
查看完整版本: 关于 __init__ 的参数的默认值