提问人:user2153235 提问时间:10/18/2023 最后编辑:user2153235 更新时间:10/25/2023 访问量:62
Spark Row 对象的实例化与重载原型不同?
Spark Row object instantiated differently from overloaded prototypes?
问:
中的 Spark 类不包含任何方法,但显示以下重载类型提示:Row
pyspark/sql/types.py
__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
上面的第二行不适合任何重载的原型。
它几乎与原型相吻合,除了所有
的参数应该是字符串。这是
显然不是 的情况,而是那个调用
在 REPL 提示符下发出时不会生成任何消息。
显然,我缺少一些关于如何
类型提示和重载有效。有人可以解释一下吗?*args
*args
Row("Alice",11)
附言对于上下文,
我通过尝试查看构造函数如何达到这一点
知道在指定字段值时指定字段名称。的源代码显示,它取决于参数列表是 还是 。中的两个方法调用
本段使用 ,但
第二个根本不适合上面的原型。Row("name","age")
Row("Alice", 11)
__new__
*args
**kwargs
Row
*args
*args
答:
Row
是 的子类,因此它的行为相应。查看源代码,我可以推断出那里使用的类型提示不执行任何运行时检查来强制执行类型(注意 [1] 下面提供了类型检查的背景)。因此,可以使用任何对象类型创建对象,而不仅仅是 int 和 strings。下面是一个例子,tuple
Row
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)
相反,默认情况下,两者都将设置元组的值。这就是为什么在您的示例中的原因row1 == row2
>>> row = Row('name', 'age')
>>> row.__fields__
# AttributeError: __fields__
>>> row1 = Row("Alice", 11)
>>> row2 = Row(name="Alice", age=11)
>>> row1 == row2
# True
这里很重要的一点是还定义了方法,该方法将创建 from 字段和值的新实例。实质上,当您以这种方式调用现有对象时,现有值将成为新分配的字段Row
__call__
Row
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] 这是关于类型提示和检查的入门。第三方工具可用于检查提示指定的类型。这没有内置在像Spyder这样的IDE中。
评论
__call__
Row('name', 'age')('Alice', 11)("Blah","Bleh")
Row(Alice='Blah',11='Bleh')
评论