Не так ясно, что функция всегда должна возвращать объекты ограниченного типа или что возвращение None является неправильным. Например, re.search может возвращать объект _sre.SRE_Match
или объект NoneType
:
import re match = re.search ( 'a', 'a') type (match) # & lt; type '_sre.SRE_Match' & gt; match = re.search ('a', 'b') type (match) # & lt; type 'NoneType' & gt;
Разработанный таким образом, вы можете проверить соответствие с idiom
, если совпадение: # do xyz
Если разработчикам потребовался re.search для возврата объекта _sre.SRE_Match
, тогда идиома должна была бы измениться на
, если match.group (1) None: # do xyz
Не было бы никакого существенного усиления, требуя, чтобы re.search всегда возвращал объект _sre.SRE_Match
.
] Итак, я думаю, что вы создаете функцию, которая должна зависеть от ситуации и, в частности, от того, как вы планируете использовать эту функцию.
Также обратите внимание, что оба _sre.SRE_Match
и NoneType
являются экземплярами объекта, поэтому в широком смысле они одного типа. Поэтому правило, что «функции всегда должны возвращать только один тип», совершенно бессмысленно.
Сказав это, есть прекрасная простота для функций, возвращающих объекты, все из которых имеют одни и те же свойства. (Утиная печать, а не статическая типизация, - это путь python!) Это может позволить вам объединить функции: foo (bar (baz))) и с уверенностью знать тип объекта, который вы получите на другом конце.
Это поможет вам проверить правильность кода. Требуя, чтобы функция возвращала только объекты определенного ограниченного типа, проверять меньше случаев. «foo всегда возвращает целое число, поэтому, когда целое число ожидается везде, я использую foo, я золотой ...»
Строковые литералы хранятся таким образом, что они доступны для жизни программы; если вы пишете
char *ptr = "This is a test";
, все, что записано на ptr
, это адрес строкового литерала "This is a test"
. Даже если переменная ptr
выходит за пределы области видимости, строковый литерал продолжает существовать в своем собственном разделе памяти, который не тот же раздел, используемый malloc
(по крайней мере, не логический уровень). Обратите внимание, что несколько экземпляров одного и того же строкового литерала могут разрешаться в одном месте; IOW, учитывая
char *p0 = "This is a test";
char *p1 = "This is a test";
p0
и p1
, могут содержать один и тот же адрес (это зависит от того, сопоставлено ли несколько вхождений строковых литералов в одно и то же место).
Когда вы вызываете Container_new
, все, что вы делаете, копирует адрес в container->buffer
и globalBuffer
; оба заканчиваются, указывая на то же самое, что существует независимо от любого из них. free
-ing container
не влияет на строковый литерал, на который указывает container->buffer
, поэтому printf(globalBuffer);
по-прежнему отображается "Test-string."
.
Итак, вы должны not вызывать
free(container->buffer);
для этой конкретной программы, так как вы не назначили результат malloc
, calloc
или realloc
.
Если вы, OTOH, вы написали Container_new
как
Container* Container_new(char* buffer)
{
Container* container = malloc(sizeof(Container));
container->buffer = malloc(strlen(buffer) + 1); // Allocate memory to
if (container->buffer) // store a *new* instance
{ // of the input string.
strcpy(container->buffer, buffer); // This will need to be
} // freed before freeing
globalBuffer = buffer; // the container
return container;
}
, то вы хотели бы освободить container->buffer
перед освобождением container
.
Вы никогда не будете free()
памятью, что вы не malloc()
ed.
Способ, которым компилятор реализует строковые литералы, не является вашим бизнесом: это деталь реализации. Вы можете free()
указатель на память, который вы выделили с помощью malloc()
, и только те, или вы рискуете жизнью своей системы.
В идеале, вызовы malloc()
и free()
вызовы должны отображаться на одном и том же «уровне проектирования» (внутри одного и того же файла реализации для того же модуля, например), и они должны идеально соответствовать: один free()
для каждого malloc()
. но это не всегда возможно.
(Обратите внимание, что некоторая библиотека выделяет блоки памяти, возвращает указатели на эти блоки и инструктирует их освобождать их. В этом случае вам разрешено освобождать эти указатели , но это плохая практика проектирования от людей, которые создали библиотеку.)
malloc()
и free()
могут быть не такими же внутри или вне библиотеки)
– Adrien Plisson
21 September 2013 в 17:04