我对Python相当陌生,我有点困惑第二个函数merge(self,l1,l2)中的l1和l2如何访问.val?如果我们没有在 merge 函数的参数中将 l1 和 l2 声明为 ListNode 那么它怎么知道 l1 和 l2 是节点并访问 .val ?
如果有人可以解释这个概念,我将非常感激。 TIA
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
if not lists or len(lists) == 0:
return None
while len(lists) > 1:
combinedList = []
for i in range(0, len(lists), 2):
l1 = lists[i]
l2 = lists[i+1] if (i+1) < len(lists) else None
combinedList.append(self.merge(l1,l2))
lists = combinedList
return lists[0]
def merge(self, l1, l2):
dummy = ListNode()
output = dummy
while l1 and l2:
if l1.val < l2.val:
output.next = l1
l1 = l1.next
else:
output.next = l2
l2 = l2.next
output = output.next
if l1:
output.next = l1
elif l2:
output.next = l2
return dummy.next
最佳答案
它是怎么知道的?很简单,事实并非如此。
除非您明确检查传递给任何给定函数的东西是否是您想要的,否则该函数 simple 也不知道您给它的东西是什么,并且会简单地失败并出现一些错误或给出一些意外的结果,如果这不是我们想要的东西。
Python 是动态类型语言,严重依赖所谓的鸭子类型,可以概括为:如果它看起来像鸭子、嘎嘎叫起来像鸭子、走路像鸭子,那么它就是鸭子。
现在让我们看一个简单的例子:
class MyObject:
def __init__(self, val):
self.val = val
这里我们定义了一些对象,其特征是具有.val属性
现在让我们创建一个函数来用它做一些事情
def fun(item:MyObject):
return item.val + 10
并快速测试
a = MyObject(10)
print(fun(a))
它会按照预期打印 20。
但是Python是一种动态语言,这意味着什么?这意味着您可以在运行时以任何方式修改对象,这样您就可以使一些完全不同的对象看起来像任何其他对象,例如
class B:
pass
b=B()
正如你所看到的,b 对象与之前的 MyObject 没有什么不同,它简单地没有任何东西,没有任何属性(除了每个类都有的默认属性之外,但我离题了),所以它绝对不会工作与有趣
,它肯定不会,这会给你带来错误
print(fun(b))
#AttributeError: 'B' object has no attribute 'val'
但你可以让它发挥作用
b.val=22
print(fun(b))
这将打印 32,这里会发生什么?我们简单地在运行时向 b 对象添加了一个新属性,现在,就 fun
而言,我们的 B 实例与 MyObject 相同,因为它有一个 .val 属性,可以添加一个数字,因此无论它是否真的是 MyObject 都无关紧要。
好的,但是 fun
的签名清楚地表明它想要一个 MyObject,对吧?这是类型注释或类型提示,它在运行时没有影响,它用于文档目的并为我们程序员和/或代码用户提供其正确预期用法的提示,以及其他第三方使用这些工具静态分析代码以检测否则可能未被检测到的错误。
关于python - 函数参数概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73017041/