从question I posted earlier开始,我试图了解函数方法中类型参数范围的详细信息。
例如:
f(x::Vector{<:Number}) = sum(x)
g(x::Vector{T}) where T<:Number = sum(x)
<:Number
约束仅覆盖f
的参数列表:
julia> methods(f)
f(x::Array{#s1,1} where #s1<:Number)
但是似乎g
是它的参数:
julia> methods(g)
g(x::Array{T,1}) where T<:Number
除了"[y]ou generally want T
to cover as little of the signature as possible"之外,style并限制了T
的范围,是否有原因?
在性能,调度或代码生成方面是否有任何暗示?
答案 0 :(得分:4)
上面的f
和g
的定义与Michael等效。您可以通过以下方式动态检查它:
julia> f(x::Vector{<:Number}) = sum(x)
f (generic function with 1 method)
julia> f(x::Vector{T}) where T<:Number = sum(x)
f (generic function with 1 method)
julia> methods(f)
# 1 method for generic function "f":
[1] f(x::Array{T,1}) where T<:Number in Main at REPL[2]:1
Julia告诉您方法定义已被覆盖(因此它被认为是等效的)。
但是,通常范围界定很重要。参见以下示例:
julia> f(::Vector{Vector{<:Real}}) = "inner"
f (generic function with 1 method)
julia> f(::Vector{Vector{T}}) where {T<:Real}= "outer"
f (generic function with 2 methods)
julia> f(::Any) = "all else"
f (generic function with 3 methods)
julia> methods(f)
# 3 methods for generic function "f":
[1] f(::Array{Array{#s1,1} where #s1<:Real,1}) in Main at REPL[1]:1
[2] f(::Array{Array{T,1},1}) where T<:Real in Main at REPL[2]:1
[3] f(::Any) in Main at REPL[3]:1
julia> f([[1]])
"outer"
julia> f(Vector{<:Real}[[1]])
"inner"
julia> f([Any[1]])
"all else"
关于常规(即类型稳定)代码的性能,Julia执行静态方法分派,因此这无关紧要。可能您可以设计一个人为设计的示例,该示例要求在其中可能很重要的情况下进行复杂的动态方法分派或动态代码生成(但是出于实际原因,这不相关,仅使用代表您需求的规范即可。)
答案 1 :(得分:1)
from django.db import models
class ArticleStat(models.Model):
...
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name='articlestats'
)
def save(self, *args, **kwargs):
try:
article = Article.objects.get(pk=self.article_id)
except Article.DoesNotExist:
pass
else:
try:
article_stat = ArticleStat.objects.get(
article=article,
elapsed_time_in_seconds=self.elapsed_time_in_seconds
)
self.id = article_stat.id
super().save(*args, **kwargs, update_fields=["hits"])
except ArticleStat.DoesNotExist:
super().save(*args, **kwargs)
和f
的语法相同,因此没有区别。