Типично для некоторых задач несколько объектов, которые имеют явные ресурсы, которые должны быть явно выпущены - скажем, два файла; Это легко выполнять, когда задача локально для функции с использованием вложенных с блоками или - даже лучше - один с блоком с несколькими with_item положениями:
with open('in.txt', 'r') as i, open('out.txt', 'w') as o:
# do stuff
< /code>
OTOH, я все еще изо всех сил пытаюсь понять, как это должно работать, когда такие объекты не просто локальны для функции, но принадлежащий экземпляру класса - другими словами, как контекстные менеджеры составляют. < /p>
Идеально я хотел бы делать что -то вроде: < /p>
Я хотел бы делать что -то вроде: < /p>
< /p>
.class Foo:
def __init__(self, in_file_name, out_file_name):
self.i = WITH(open(in_file_name, 'r'))
self.o = WITH(open(out_file_name, 'w'))
и попросить Foo само по себе превращение в диспетчер контекста, который обрабатывает i и o , так что когда я делаю
with Foo('in.txt', 'out.txt') as f:
# do stuff
< /code>
self.i< /code> и self.o < /code> позаботится автоматически, как и следовало ожидать.class Foo:
def __init__(self, in_file_name, out_file_name):
self.i = open(in_file_name, 'r').__enter__()
self.o = open(out_file_name, 'w').__enter__()
def __enter__(self):
return self
def __exit__(self, *exc):
self.i.__exit__(*exc)
self.o.__exit__(*exc)
< /code>
but it's both verbose and unsafe against exceptions occurring in the constructor. After searching for a while, I found this 2015 blog post, which uses contextlib.ExitStack< /code> Чтобы получить что -то очень похожее на то, что я после: < /p>
class Foo(contextlib.ExitStack):
def __init__(self, in_file_name, out_file_name):
super().__init__()
self.in_file_name = in_file_name
self.out_file_name = out_file_name
def __enter__(self):
super().__enter__()
self.i = self.enter_context(open(self.in_file_name, 'r')
self.o = self.enter_context(open(self.out_file_name, 'w')
return self
< /code>
This is pretty satisfying, but I'm perplexed by the fact that:
[list]
[*]I find nothing about this usage in the documentation, so it doesn't seem to be the "official" way to tackle this problem;
[*]in general, I find it extremely difficult to find information about this issue, which makes me think I'm trying to apply an unpythonic solution to the problem.
[/list]
[b]Some extra context[/b]: I work mostly in C++, where there is no distinction between the block-scope case and the object-scope case for this issue, as this kind of cleanup is implemented inside the destructor (think __del__
, но вызывает детерминированно), а деструктор (даже если не явно определяется) автоматически вызывает деструкторы субобъектов. Итак, оба: < /p>
{
std::ifstream i("in.txt");
std::ofstream o("out.txt");
// do stuff
}
< /code>
and
struct Foo {
std::ifstream i;
std::ofstream o;
Foo(const char *in_file_name, const char *out_file_name)
: i(in_file_name), o(out_file_name) {}
}
{
Foo f("in.txt", "out.txt");
}
< /code>
do all the cleanup automatically as you generally want.
I'm looking for a similar behavior in Python, but again, I'm afraid I'm just trying to apply a pattern coming from C++, and that the underlying problem has a radically different solution that I can't think of.
So, to sum it up: what is the Pythonic solution to the problem of having an object who owns objects that require cleanup become a context-manager itself, calling correctly the __enter__
Типично для некоторых задач несколько объектов, которые имеют явные ресурсы, которые должны быть явно выпущены - скажем, два файла; Это легко выполнять, когда задача локально для функции с использованием вложенных с блоками или - даже лучше - один с блоком с несколькими with_item положениями:
[code]with open('in.txt', 'r') as i, open('out.txt', 'w') as o: # do stuff < /code>
OTOH, я все еще изо всех сил пытаюсь понять, как это должно работать, когда такие объекты не просто локальны для функции, но принадлежащий экземпляру класса - другими словами, как контекстные менеджеры составляют. < /p>
but it's both verbose and unsafe against exceptions occurring in the constructor. After searching for a while, I found this 2015 blog post, which uses contextlib.ExitStack< /code> Чтобы получить что -то очень похожее на то, что я после: < /p>
This is pretty satisfying, but I'm perplexed by the fact that:
[list] [*]I find nothing about this usage in the documentation, so it doesn't seem to be the "official" way to tackle this problem; [*]in general, I find it extremely difficult to find information about this issue, which makes me think I'm trying to apply an unpythonic solution to the problem. [/list]
[b]Some extra context[/b]: I work mostly in C++, where there is no distinction between the block-scope case and the object-scope case for this issue, as this kind of cleanup is implemented inside the destructor (think __del__[/code], но вызывает детерминированно), а деструктор (даже если не явно определяется) автоматически вызывает деструкторы субобъектов. Итак, оба: < /p>
do all the cleanup automatically as you generally want.
I'm looking for a similar behavior in Python, but again, I'm afraid I'm just trying to apply a pattern coming from C++, and that the underlying problem has a radically different solution that I can't think of.
So, to sum it up: what is the Pythonic solution to the problem of having an object who owns objects that require cleanup become a context-manager itself, calling correctly the __enter__[/code]/[code]__exit__[/code] своих детей?
Типично для некоторых задач несколько объектов, которые имеют явные ресурсы, которые должны быть явно выпущены - скажем, два файла; Это легко выполнять, когда задача локально для функции с использованием вложенных с блоками или - даже лучше - один с...
Мне трудно писать чистый код с контекстными менеджерами в Python, не попадая в администратор контекста. Представьте себе что-то вроде:
class A:
def __init__(self):
self.b = B() # where B is a context manager
Мне трудно писать чистый код с контекстными менеджерами в Python, не попадая в администратор контекста. Представьте себе что-то вроде:
class A:
def __init__(self):
self.b = B() # where B is a context manager
Мне трудно писать чистый код с контекстными менеджерами в Python, не попадая в администратор контекста. Представьте себе что-то вроде:
class A:
def __init__(self):
self.b = B() # where B is a context manager
Как (в Python 3) получить значения всех свойств, принадлежащих определенному классу. Мне нужны ТОЛЬКО те значения (свойства), которые определены в определенном классе без наследуемых.