On Friday, March 2, 2018 at 3:37:25 PM UTC, Paul Moore wrote: > [...] > RAII works in C++ (where it was initially invented) because it's used > with stack-allocated variables that have clearly-defined and limited > scope.
RAII also works with smart pointers, which are a closer analogue to python references. > In my experience writing C++, nobody uses RAII with > heap-allocated variables - those require explicit allocation and > deallocation and so are equivalent to having an explicit "close()" > method in Python (or using __del__ in CPython as it currently exists). In my experience no-one has been been explicitly deallocating heap-variables for many years: they have been using smart pointers and RAII. > Python doesn't have stack allocation, nor does it have a deterministic > order of deletion of objects when their last reference goes out of > scope (which can happen simultaneously for many objects): > > class Tracker: > def __init__(self, n): > self.n = n > def __del__(self): > print("Deleting instance", self.n) > > def f(): > a = Tracker(1) > b = Tracker(2) > > f() > > The language doesn't guarantee that a is removed before b. Are you > proposing to make that change to the language as well? It would improve things more, but I have not included such a proposal in the current PEP as this is not essential for the main benefit. > Also Python only has function scope, so variables local to a > smaller-than-the-function block of code aren't possible. That's > something that is used in C++ a lot to limit the lifetime of resources > under RAII. How do you propose to address that (without needing > explicit del statements)? Create a sub function. > That's why the with statement exists, to > clearly define lifetimes smaller than "the enclosing function". It does that in a half-hearted and smelly way compared to a function: The object references are left dangling in a broken state (not invariant). In fact you would do well to wrap your "with"s in a function to contain the smell. > Your proposal doesn't offer any equivalent (other than an extra function). An equivalent is not needed. Using a function is the ideomatic and does not leak - unlike the "with" hack. (IMO block-scoping would enhance the langauge but is not essential so not in this PEP). > Consider C++: > > void fn() { > for (i = 0; i < 10000; ++i) { > char name[100]; > sprintf(name, "file%d.txt, i); > File f(name); // I don't think std::ofstream doesn't support RAII > f << "Some text"; > } > } > > Or (real Python): > > def fn(): > for i in range(10000): > with open(f"file{i}.txt", "w") as f: > f.write("Some text") > > How would you write this in your RAII style - without leaving 10,000 > file descriptors open until the end of the function? def write_some_text_to_file(fname): f = RAIIFileAccess(fname, 'w') f.write("Some text") def fn(): for i in range(10000): write_some_text_to_file(f"file{i}.txt") > That's both less efficient (function calls have a cost) Oh come now. No one is choosing to use python for its efficiency and functions that deal with real resources, such as files, are likely dominated by the os fopen/close etc. > and less maintainable than the with-statement version. I disagree. Even for such a trivial example, as soon as you start to change the detail of what you do then the usual maintainability benefits of small well factored functions comes into play. That's why we have functions in the language isn't it? Or do you just write one long script? -- https://mail.python.org/mailman/listinfo/python-list