我在 Julia 中创建了一个类型(结构)。
struct ExampleStruct
data::DataFrame
end
它有一些相关的函数/方法,我想为其编写单元测试。
这是一个弥补测试的示例。
function has_names(df)
return length(names(df)) > 0
end
我有点被两个问题困扰。
这是我打算用于测试的数据。
test_data = [
["col1", "col2", "col3"],
["1", "2", "3"],
["1a", "2a" "3a"],
["1b", "2b" "3b"],
]
如果我直接测试
DataFrame
,我可以使用以下构造函数来初始化它。
example_df = DataFrame(test_data[2:end, :], Symbol.(test_data[1, :]))
但是由于
DataFrame
包含在结构 ExampleStruct
中,因此 ExampleStruct
构造函数需要某种方式来接受这种类型的数据并将其传递给 DataFrame
构造函数。 (可能吧。)
# inner constructor
function ExampleStruct( arg? )
data(arg) # ?
end
# outer constructor
function ExampleStruct( test_data? )
ExampleStruct(test_data) # calling the inner constructor here??
end
当不运行单元测试,但运行正常代码时,将从文件加载数据。可能有多种可能的文件格式,其中之一是 CSV。
因此,在“正常”(不是测试)代码中,
ExampleStruct
的构造函数应该执行类似的操作来初始化data
:
# elsewhere, but could be a different file type as well
#using CSV
#csvfile = CSV.File(filename)
#
data = DataFrame(csvfile)
这里“缺失的一块拼图”是
ExampleStruct
的构造函数。 (我想。)我不知道如何写。 (从我为上面的“内部”和“外部构造函数”提供的草图代码中这可能是显而易见的。)
我认为它需要两种方法,因为它需要处理两种情况。
DataFrame
数据的情况。这用于测试。在本例中,我使用 Vector{Vector{String}}
来存储数据,但如果其他类型更容易使用,也可以是其他类型。 (使用 Vector{Vector{T}}
时很难定义列名称。)DataFrame
的情况。它可能是 CSV.File
也可能是其他格式。我猜想有一种方法可以使用抽象类型来表达这一点,抽象类型是所有可能的文件类型的联合。我对 Julia 不太了解 - 这只是我通过阅读文档对它如何工作的感觉。我希望这个问题有意义。我才刚刚开始与 Julia 合作,所以目前这一切都超出了我的知识范围。
如果我用 Python 来做这件事,我可能会写这样的东西:
class ExampleStruct:
def __init__(self, arg):
if isinstance(arg, list):
self.data = DataFrame(arg[1:], cols=arg[0])
else:
# assume arg is some kind of file object, init from this
以上内容应视为伪代码。更好的设计可能是使用
kwargs
而不是检查 arg
的类型。
您的问题实际上是关于如何将一个结构封装在另一个数据结构中,这对于任何具有对象能力的语言来说都是基础。本质上,您可以寻址您选择在结构中调用
data
的 DataFrame 成员:
struct ExampleStruct
data::DataFrame
end
用“.”运算符,因此如果
examp
是 ExampleStruct
,则其 DataFrame
成员将作为 examp.data
进行访问。
请参阅 https://docs.julialang.org/en/v1/manual/types/#Composite-Types。您给出了一个 Python 示例,Python 类是相似的,尽管它们通常不在声明中键入结构成员,并且许多 Python 类通过使用而不是显式声明其成员的事实可能使您无法学习这一点:(。
所以你有例如:
using CSV
using DataFrames
struct ExampleStruct
data::DataFrame
end
function has_names(df::DataFrame)
return length(names(df)) > 0
end
has_names(examplestruct::ExampleStruct) = has_names(examplestruct.data)
# here we give a Matrix rather than the vector of vectors you did
test_data = [
"col1" "col2" "col3";
"1" "2" "3";
"1a" "2a" "3a";
"1b" "2b" "3b";
]
example_df = DataFrame(test_data[2:end, :], Symbol.(test_data[1, :]))
打印
testexample = ExampleStruct(3×3 DataFrame
Row │ col1 col2 col3
│ String String String
─────┼────────────────────────
1 │ 1 2 3
2 │ 1a 2a 3a
3 │ 1b 2b 3b)
has_names(testexample) = true
.