В JavaScript тип значения исключительно определяет, будет ли это значение присвоено копией значения или копией-копией.
Примитивные значения всегда назначаются / передаются по значению-копии :
null
undefined
ES6
Соединение значения всегда назначаются / передаются по референс-копии
Например
var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]
В приведенном выше фрагменте, поскольку 2
является скалярным примитивом, a
содержит одну начальную копию этого значения, а b
присваивается другая копия значения , При изменении b
вы никоим образом не изменяете значение в a
.
Но оба c
и d
являются отдельными ссылками на одно и то же общее значение [1,2,3]
, которое является составная величина. Важно отметить, что ни c
, ни d
больше не «владеют» значением [1,2,3]
- оба равны равным равноправным ссылкам на значение. Таким образом, при использовании любой ссылки для изменения (.push(4)
) фактического общего значения array
, это влияет только на одно общее значение, и обе ссылки будут ссылаться на вновь измененное значение [1,2,3,4]
.
var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]
Когда мы выполняем присваивание b = [4,5,6]
, мы ничего не делаем, чтобы повлиять на a
, где [1,2,3]
все еще ссылается. Для этого b
должен быть указателем на a
, а не ссылкой на array
, но в JS нет такой возможности
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// later
x = [4,5,6];
x.push( 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // [1,2,3,4] not [4,5,6,7]
Когда мы проходим аргумент a
, он присваивает копию ссылки a
на x
. x
и a
- отдельные ссылки, указывающие на то же значение [1,2,3]
. Теперь внутри функции мы можем использовать эту ссылку для мутации самого значения (push(4)
). Но когда мы выполняем присваивание x = [4,5,6]
, это никоим образом не влияет на то, где указывается начальная ссылка a
, - все еще указывает на значение (теперь измененное) [1,2,3,4]
.
Чтобы эффективно пройти составное значение (например, array
) по копированию значения, вам нужно вручную сделать его копию, чтобы переданная ссылка не все еще указывала на оригинал. Например:
foo( a.slice() );
Составное значение (объект, массив и т. Д.), Которое может быть передано посредством reference-copy
function foo(wrapper) {
wrapper.a = 42;
}
var obj = {
a: 2
};
foo( obj );
obj.a; // 42
Здесь obj
действует как обертка для скалярное примитивное свойство a
. Когда передано foo(..)
, копия ссылки obj
передается и устанавливается в параметр wrapper
. Теперь мы можем использовать ссылку wrapper
для доступа к общему объекту и обновить его свойство. После завершения функции obj.a
вы увидите обновленное значение 42
.
select
, предпочтительнее, когда это решение является одним лайнером (проще поддерживать, меньше рисковать при неправильном использовании) и использует select под капотом (реализация такая же, как ответ @DanielStuzbach) ,
– Trevor Boyd Smith
21 November 2017 в 17:26
попробуйте это, он использует базовый C.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET,SO_RCVTIMEO, timeval)
SO_RCVTIMEO
и SO_SNDTIMEO
.
– jtpereyda
30 June 2018 в 20:59
Вы можете установить время ожидания до получения ответа и после получения ответа установить его обратно на None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
Как упоминалось, оба select.select()
и socket.settimeout()
будут работать.
Обратите внимание, что вам может потребоваться дважды settimeout
для ваших нужд , например
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()
# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)
.settimeout()
более одного раза, вы можете на первый взгляд вызвать метод setdefaulttimeout()
.
– mvarge
17 November 2016 в 22:40
Тайм-аут, который вы ищете, - это тайм-аут сокета подключения, а не основной сокет, если вы реализуете серверную сторону. Другими словами, есть еще один тайм-аут для объекта сокета соединения, который является выходом метода socket.accept()
. Поэтому:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5) # This is the one that affects recv() method.
connection.gettimeout() # This should result 5
sock.gettimeout() # This outputs None when not set previously, if I remember correctly.
Если вы реализуете клиентскую сторону, это будет просто.
sock.connect(server_address)
sock.settimeout(3)