Спасибо всем за ваш вклад, но проблема была в другом. Это было то, что я устанавливал печенье после того, как мои заголовки были отправлены. Теперь это не значит, что мне нужно было установить cookie в верхней части моего файла, но у меня были некоторые комментарии и пробелы в верхней части моего файла, и удаление этих файлов позволило избавиться от ошибки заголовков. Если удаление пробелов не устраняет ошибку заголовков, попробуйте использовать ob_start()
перед установкой файла cookie и ob_end_flush();
после. Но это не лучшая практика.
Я также получал предупреждение для неопределенных индексов, где у меня были определены переменные. Проверка, установлены ли значения, перед тем, как присваивать их переменным, которые я использую внутри, также помог оператор if.
$username = isset( Спасибо всем за ваш вклад, но проблема была в другом. Это было то, что я устанавливал печенье после того, как мои заголовки были отправлены. Теперь это не значит, что мне нужно было установить cookie в верхней части моего файла, но у меня были некоторые комментарии и пробелы в верхней части моего файла, и удаление этих файлов позволило избавиться от ошибки заголовков. Если удаление пробелов не устраняет ошибку заголовков, попробуйте использовать ob_start()
перед установкой файла cookie и ob_end_flush();
после. Но это не лучшая практика.
Я также получал предупреждение для неопределенных индексов, где у меня были определены переменные. Проверка, установлены ли значения, перед тем, как присваивать их переменным, которые я использую внутри, также помог оператор if.
[110]POST['username']) ? Спасибо всем за ваш вклад, но проблема была в другом. Это было то, что я устанавливал печенье после того, как мои заголовки были отправлены. Теперь это не значит, что мне нужно было установить cookie в верхней части моего файла, но у меня были некоторые комментарии и пробелы в верхней части моего файла, и удаление этих файлов позволило избавиться от ошибки заголовков. Если удаление пробелов не устраняет ошибку заголовков, попробуйте использовать ob_start()
перед установкой файла cookie и ob_end_flush();
после. Но это не лучшая практика.
Я также получал предупреждение для неопределенных индексов, где у меня были определены переменные. Проверка, установлены ли значения, перед тем, как присваивать их переменным, которые я использую внутри, также помог оператор if.
[110]POST['username'] : '';
$enterpass = isset( Спасибо всем за ваш вклад, но проблема была в другом. Это было то, что я устанавливал печенье после того, как мои заголовки были отправлены. Теперь это не значит, что мне нужно было установить cookie в верхней части моего файла, но у меня были некоторые комментарии и пробелы в верхней части моего файла, и удаление этих файлов позволило избавиться от ошибки заголовков. Если удаление пробелов не устраняет ошибку заголовков, попробуйте использовать ob_start()
перед установкой файла cookie и ob_end_flush();
после. Но это не лучшая практика.
Я также получал предупреждение для неопределенных индексов, где у меня были определены переменные. Проверка, установлены ли значения, перед тем, как присваивать их переменным, которые я использую внутри, также помог оператор if.
[110]POST['password']) ? Спасибо всем за ваш вклад, но проблема была в другом. Это было то, что я устанавливал печенье после того, как мои заголовки были отправлены. Теперь это не значит, что мне нужно было установить cookie в верхней части моего файла, но у меня были некоторые комментарии и пробелы в верхней части моего файла, и удаление этих файлов позволило избавиться от ошибки заголовков. Если удаление пробелов не устраняет ошибку заголовков, попробуйте использовать ob_start()
перед установкой файла cookie и ob_end_flush();
после. Но это не лучшая практика.
Я также получал предупреждение для неопределенных индексов, где у меня были определены переменные. Проверка, установлены ли значения, перед тем, как присваивать их переменным, которые я использую внутри, также помог оператор if.
[110]POST['password'] : '';
It's not very Pythonic, but if you really must:
import inspect
def compact(*names):
caller = inspect.stack()[1][0] # caller of compact()
vars = {}
for n in names:
if n in caller.f_locals:
vars[n] = caller.f_locals[n]
elif n in caller.f_globals:
vars[n] = caller.f_globals[n]
return vars
def extract(vars):
caller = inspect.stack()[1][0] # caller of extract()
for n, v in vars.items():
caller.f_locals[n] = v # NEVER DO THIS - not guaranteed to work
I've used these implementations quite a bit, and they work, but technically modifying f_locals
is not supported.
Seriously though, if you really feel you have a need to use these functions, you're probably doing something the wrong way. It seems to run against Python's philosophy on at least three counts: "explicit is better than implicit", "simple is better than complex", "if the implementation is hard to explain, it's a bad idea", maybe more (and really, if you have enough experience in Python you know that stuff like this just isn't done). I could see it being useful for a debugger or post-mortem analysis, or perhaps for some sort of very general framework that frequently needs to create variables with dynamically chosen names and values, but it's a stretch.
If you are going to use these functions, you should at least keep the extract
ed variables contained to within small scopes. Wrap them in functions that you can then consider to be "black boxes". The main reason extract
is bad is that it puts variables in your symbol table in a way that isn't clear from inspecting the code. If you keep the effects of those variables localized to a very small function, and explain what you're doing with clear code and comments, it's not that big of a problem.
Боюсь, в Python нет аналогов. В некоторой степени вы можете смоделировать их эффект, используя (и передавая) locals
:
>>> def compact(locals, *keys):
... return dict((k, locals[k]) for k in keys)
...
>>> a = 10
>>> b = 2
>>> compact(locals(), 'a', 'b')
{'a': 10, 'b': 2}
>>> def extract(locals, d):
... for k, v in d.items():
... locals[k] = v
...
>>> extract(locals(), {'a': 'foo', 'b': 'bar'}
>>> a
'foo'
>>> b
'bar'
Тем не менее, я не думаю, что эти функции «чрезвычайно удобны». Динамические глобальные / локальные переменные являются злыми и подверженными ошибкам - ребята из PHP узнали об этом, когда не одобряли register_globals. По моему опыту, немногие опытные программисты PHP или основные фреймворки используют compact ()
или extract ()
.
В Python явное лучше, чем неявное :
a = 1
b = 2
# compact
c = dict(a=a, b=b)
# extract
a, b = d['a'], d['b']
Is it worth pointing out that extract()
(and to a lesser extent, compact()
) is one of the most "evil" features of PHP (along with register_globals
and eval
), and should be avoided?
extract
makes it much harder to determine where a variable was defined. When it is harder to trace a variable back to where it was defined, it's harder to check for common security problems like using uninitialized variables, or unfiltered variables which originated from user input.
compact
is not as bad, but if used badly can still make it more difficult than it would otherwise be to see where an array member gets set from a variable.
The equivalent of extract()
in many other languages is the with
keyword. Python now has a with
keyword, though it works a bit differently, making it not quite like extract()
. However, in other languages such as Javascript, the with
keyword also has a poor reputation.
I think the best advice would be to think differently - instead of trying to emulate a bad feature of PHP, think of other ways to do what you want to do with concise and readable code.
Я предполагаю, что эквивалент extract ($ x)
равен globals (). Update (x)
, как и для compact ()
это подмножество vars ()
>>> foo, bar, baz = 1, 2, 3
# extract
>>> globals().update({"foo": 4, "qux": 5})
>>> foo
4
>>> qux
5
# compact
>>> d = dict((k, v) for k, v in vars().iteritems() if k in ["foo", "bar"])
>>> d
{'bar': 2, 'foo': 1}
PHP's compact function in Python (works with 2.6; not guaranteed to work with earlier versions of Python):
import inspect
def compact(*args):
return dict([(i, inspect.currentframe().f_back.f_locals.get(i, None))
for i in args])
I've written more extensively about this: Python can be just as ugly as PHP.