pyspark 示例化的Spark Row对象与重载原型不同?

qmelpv7a  于 2023-11-16  发布在  Spark
关注(0)|答案(1)|浏览(154)

pyspark/sql/types.py中的Spark Row类不包含__init__方法,但显示了以下__new__的重载类型提示:

@overload
def __new__(cls, *args: str) -> "Row"

@overload
def __new__(cls, **kwargs: Any) -> "Row"

def __new__(cls, *args: Optional[str], **kwargs: Optional[Any]) -> "Row"

字符串
Row的文档字符串显示了各种示例化:

>>> Person = Row("name", "age")
>>> row1 = Row("Alice", 11) # This is the one that is hard to understand
>>> row2 = Row(name="Alice", age=11)
>>> row1 == row2
True


上面的 * 第二 * 行不适合任何重载的原型。它 * 几乎 * 适合*args的原型,除了*args的所有参数都应该是 * 字符串 * 的事实。这显然不是Row("Alice",11)的情况,但是在REPL提示符下发出调用时不会生成任何消息。显然,关于类型提示和重载是如何工作的,我有些东西不知道。2有人能解释一下吗?

**P.S.**关于上下文,我是通过尝试了解构造函数如何知道Row("name","age")指定字段名,而Row("Alice", 11)指定字段值来达到这一点的。__new__的源代码显示,它取决于参数列表是*args还是**kwargs。本段中的两个Row方法调用都使用*args,但是第二个根本不适合上面的*args的原型。

krcsximq

krcsximq1#

Rowtuple的子类,因此它的行为也是如此。查看源代码,我可以推断出这里使用的类型提示不执行任何运行时检查来强制执行类型(下面的注解[1]提供了类型检查的背景)。因此,Row对象可以使用任何对象类型创建,而不仅仅是int和string。这里是一个例子,

class Foo:
    pass

class Bar:
    pass

>>> Row(Foo(), Bar())
# <Row(<__main__.Foo object at 0x7f5bb3ef4700>, <__main__.Bar object at 0x7f5bb36458d0>)>

字符串
仅使用args创建行对象不会自动设置__fields__参数。因此,您的假设“对于上下文,我通过尝试查看构造函数如何知道Row("name","age")指定字段名,而Row("Alice", 11)指定字段值”是不正确的。
相反,默认情况下,两者都将设置元组的值。

>>> row = Row('name', 'age')
>>> row.__fields__
# AttributeError: __fields__

>>> row1 = Row("Alice", 11)
>>> row2 = Row(name="Alice", age=11)
>>> row1 == row2
# True


这里有一点很重要,Row还定义了__call__方法,该方法将从字段和值创建Row的新示例。

>>> row = Row('name', 'age')('Alice', 11)
>>> row
# Row(name='Alice', age=11)

>>> row.__fields__
>>> <Row('name', 'age')>


但是当您使用kwargs表单时,字段和值是自动设置的,

>>> row = Row(name="Alice", age=11)
>>> row
# Row(name='Alice', age=11)

>>> row.__fields__
# ['name', 'age']

备注:
[1]Here是类型提示和检查的入门,可以使用第三方工具来检查提示指定的类型。这是not built into IDEs like Spyder

相关问题