本文将带您了解关于Swift数组分配不一致的新内容,同时我们还将为您解释既不是引用也不是深拷贝是否有原因?的相关知识,另外,我们还将为您提供关于8.7Swift类是引用类型、C#在foreach中重用
本文将带您了解关于Swift数组分配不一致的新内容,同时我们还将为您解释既不是引用也不是深拷贝是否有原因?的相关知识,另外,我们还将为您提供关于8.7 Swift类是引用类型、C# 在 foreach 中重用变量是否有原因?、celery + redis 是否存在任务分配不均的原因?、C#在foreach中重用变量是否有原因?的实用信息。
本文目录一览:- Swift数组分配不一致(既不是引用也不是深拷贝)是否有原因?(swift 数组)
- 8.7 Swift类是引用类型
- C# 在 foreach 中重用变量是否有原因?
- celery + redis 是否存在任务分配不均的原因?
- C#在foreach中重用变量是否有原因?
Swift数组分配不一致(既不是引用也不是深拷贝)是否有原因?(swift 数组)
我正在阅读文档,并且不断对语言的一些设计决策摇头。但真正让我感到困惑的是数组是如何处理的。
我冲到操场上尝试了这些。你也可以试试。所以第一个例子:
var a = [1, 2, 3]var b = aa[1] = 42ab
Here a
and b
are both [1, 42, 3]
,我可以接受。数组被引用 - 好的!
现在看这个例子:
var c = [1, 2, 3]var d = cc.append(42)cd
c
是[1, 2, 3, 42]
但是d
是[1, 2,3]
。也就是说,d
在上一个例子中看到了变化,但在这个例子中没有看到。文档说那是因为长度改变了。
现在,这个怎么样:
var e = [1, 2, 3]var f = ee[0..2] = [4, 5]ef
e
是[4, 5, 3]
,这很酷。有一个多索引替换很好,但f
即使长度没有改变,仍然看不到变化。
总而言之,如果您更改 1 个元素,对数组的常见引用会看到更改,但如果您更改多个元素或附加项目,则会创建一个副本。
这对我来说似乎是一个非常糟糕的设计。我这样想对吗?有没有理由我不明白为什么数组应该这样?
编辑 :数组已更改,现在具有值语义。理智多了!
答案1
小编典典请注意, Xcode beta 3 版本(博客文章) 中更改了数组语义和语法 ,因此该问题不再适用。以下答案适用于 beta
2:
这是出于性能原因。基本上,他们尽量避免复制数组(并声称“类似 C
的性能”)。引用语言书:
对于数组,仅当您执行可能修改数组长度的操作时才会进行复制。这包括追加、插入或删除项目,或使用范围下标替换数组中的一系列项目。
我同意这有点令人困惑,但至少对它的工作原理有一个清晰而简单的描述。
该部分还包括有关如何确保唯一引用阵列、如何强制复制阵列以及如何检查两个阵列是否共享存储的信息。
8.7 Swift类是引用类型
/**
类是引用类型
*/
/**
我们说Swift中的类和结构体非常的相似。
但是这个是表面的,它们背后的机制和原理在switf的设计中是完全不一样的。
*/
/**
下面将Swift中的 类和结构体最重要的不同点
类是引用类型,结构体是值类型。
类有继承 结构体没有继承
类有属性和行为 结构体也有属性和行为
*/
class Rect {
// 结构体成员变量
var width: Double = 5.0
var height: Double = 6.0
// 结构体的成员方法,可以访问使用成员属性。
func getWidth() -> Double {
return width
}
func show() -> Void {
print("width\(width)")
}
}
var rect1: Rect = Rect()
var rect2: Rect = rect1
print("---------------->")
print("rect1.width==\(rect1.width)")
print("rect1.height==\(rect1.height)")
// 改变rect1 的宽度
rect1.width = 100.0
print("rect2.width==\(rect2.width)")
print("rect2.height==\(rect2.height)")
/**
我们可以看到
rect1 赋给 rect2 后,改变 rect1的宽度,那么 rect2的宽度也改变了。
说明是让rect2指向rect1。 也就是它们两个指向同一个实例。
说明类是引用类型
*/
C# 在 foreach 中重用变量是否有原因?
在 C# 中使用 lambda 表达式或匿名方法时,我们必须警惕访问修改后的闭包陷阱。例如:
foreach (var s in strings){ query = query.Where(i => i.Prop == s); // access to modified closure ...}
由于修改了闭包,上面的代码将导致Where
查询中的所有子句都基于s
.
正如这里所解释的,发生这种情况是因为上面循环中s
声明的变量foreach
在编译器中是这样翻译的:
string s;while (enumerator.MoveNext()){ s = enumerator.Current; ...}
而不是这样:
while (enumerator.MoveNext()){ string s; s = enumerator.Current; ...}
正如这里所指出的,在循环之外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是如果您打算在循环范围之外使用变量:
string s;while (enumerator.MoveNext()){ s = enumerator.Current; ...}var finalString = s;
然而,在循环中定义的变量foreach
不能在循环外使用:
foreach(string s in strings){}var finalString = s; // won''t work: you''re outside the scope.
因此,编译器声明变量的方式使其极易出现通常难以发现和调试的错误,同时不会产生明显的好处。
有没有什么你可以用foreach
这种方式来处理循环,如果它们是用内部范围的变量编译的,或者这只是在匿名方法和 lambda 表达式可用或常见之前做出的任意选择,并且没有从那以后就没有修改过?
答案1
小编典典编译器声明变量的方式使其极易出现通常难以查找和调试的错误,同时不会产生明显的好处。
你的批评完全有道理。
如果使用内部范围的变量编译它们,您是否可以通过这种方式对 foreach 循环执行某些操作?或者这只是在匿名方法和 lambda 表达式可用或常见之前做出的任意选择,并且从那时起就没有修改过?
后者。C# 1.0 规范实际上并没有说明循环变量是在循环体内部还是外部,因为它没有明显的区别。在 C# 2.0 中引入闭包语义时,选择将循环变量放在循环之外,这与“for”循环一致。
我认为公平地说,所有人都对这个决定感到遗憾。这是 C# 中最糟糕的“陷阱”之一,我们将采取重大更改来修复它。在 C# 5 中,foreach 循环变量在逻辑上位于循环体中,因此闭包每次都会获得一个新副本。
for
循环不会更改,更改不会“向后移植”到以前的 C# 版本。因此,在使用此成语时应继续小心。
celery + redis 是否存在任务分配不均的原因?
如何解决celery + redis 是否存在任务分配不均的原因??
我们曾经使用 celery 任务队列系统将 redis 作为代理,将 rpc 作为后端。如果我们将 50 个任务发送给 5 个工人,那么每个工人最终会可靠地完成 10 个任务。 现在我们切换到redis作为后端和broker,有的worker拿到20个任务,有的拿到1个,似乎完全是随意的。除了后端 + 代理更改之外,没有任何代码更改。这有什么原因吗?
我运行的代码很简单:
from time import sleep
def multiply(self,num_1,num_2):
sleep(50)
return num_1 * num_2
我目前在 30 个节点上运行了 1000 次,有些工作人员正在运行 0 个任务,有些正在运行 11 个。我真的不明白为什么有些工作人员在队列中还有任务等待时会有 0 个任务运行。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
C#在foreach中重用变量是否有原因?
在C#中使用lambda表达式或匿名方法时,我们必须警惕 对修改后的闭包 陷阱的 访问 。例如:
foreach (var s in strings){ query = query.Where(i => i.Prop == s); // access to modified closure ...}
由于修改后的闭包,上述代码将导致Where
查询中的所有子句都基于的最终值s
。
正如解释在这里,这是因为该s
变量在声明foreach
环以上的编译器编译如下:
string s;while (enumerator.MoveNext()){ s = enumerator.Current; ...}
而不是像这样:
while (enumerator.MoveNext()){ string s; s = enumerator.Current; ...}
如此处所指出的,在循环外声明变量没有性能优势,在正常情况下,我能想到的唯一原因是如果您打算在循环范围外使用变量:
string s;while (enumerator.MoveNext()){ s = enumerator.Current; ...}var finalString = s;
但是,foreach
循环中定义的变量不能在循环外使用:
foreach(string s in strings){}var finalString = s; // won''t work: you''re outside the scope.
因此,编译器以某种方式声明该变量,使其极易出现通常难以查找和调试的错误,同时不会产生明显的收益。
是否可以通过foreach
这种方式对循环执行某些操作,如果它们是使用内部作用域变量进行编译则无法做到的,或者这只是在匿名方法和lambda表达式可用或通用之前做出的任意选择,并且没有从那以后就没有修改过?
答案1
小编典典编译器以一种很容易出错的方式声明该变量,该错误通常很难查找和调试,同时不会产生明显的好处。
您的批评是完全有道理的。
我在这里详细讨论这个问题:
关闭循环变量被认为是有害的
使用foreach循环,是否可以通过内部作用域变量进行编译而无法做到?还是这只是在匿名方法和lambda表达式可用或通用之前做出的任意选择,并且此后没有进行过修改?
后者。实际上,C#1.0规范没有说明循环变量是在循环体内还是在循环体内,因为它没有明显的区别。在C#2.0中引入闭包语义时,已做出选择,将循环变量置于循环之外,与“
for”循环一致。
我认为可以说所有人都对该决定表示遗憾。这是C#中最糟糕的“陷阱”之一, 我们将进行重大更改来修复它。 在C#5中,foreach循环变量在逻辑上将
位于 循环体内,因此闭包每次都会获得新的副本。
该for
循环将不会改变,并且改变不会是“向后移植”到C#的早期版本。因此,在使用此惯用语时,您应继续小心。
今天关于Swift数组分配不一致和既不是引用也不是深拷贝是否有原因?的讲解已经结束,谢谢您的阅读,如果想了解更多关于8.7 Swift类是引用类型、C# 在 foreach 中重用变量是否有原因?、celery + redis 是否存在任务分配不均的原因?、C#在foreach中重用变量是否有原因?的相关知识,请在本站搜索。
本文标签: