Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

namedtuple: raise an exception when the given class name would override an existing name #66753

Closed
fhaxbox66googlemailcom mannequin opened this issue Oct 6, 2014 · 5 comments
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@fhaxbox66googlemailcom
Copy link
Mannequin

fhaxbox66googlemailcom mannequin commented Oct 6, 2014

BPO 22563
Nosy @mdickinson, @vadmium

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2014-10-06.08:40:17.034>
created_at = <Date 2014-10-06.05:10:55.254>
labels = ['type-feature', 'library']
title = 'namedtuple: raise an exception when the given class name would override an existing name'
updated_at = <Date 2014-10-06.13:37:08.759>
user = 'https://bugs.python.org/fhaxbox66googlemailcom'

bugs.python.org fields:

activity = <Date 2014-10-06.13:37:08.759>
actor = 'fhaxbox66@googlemail.com'
assignee = 'none'
closed = True
closed_date = <Date 2014-10-06.08:40:17.034>
closer = 'mark.dickinson'
components = ['Library (Lib)']
creation = <Date 2014-10-06.05:10:55.254>
creator = 'fhaxbox66@googlemail.com'
dependencies = []
files = []
hgrepos = []
issue_num = 22563
keywords = []
message_count = 5.0
messages = ['228641', '228647', '228649', '228659', '228681']
nosy_count = 3.0
nosy_names = ['mark.dickinson', 'fhaxbox66@googlemail.com', 'martin.panter']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = None
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue22563'
versions = ['Python 3.4']

@fhaxbox66googlemailcom
Copy link
Mannequin Author

fhaxbox66googlemailcom mannequin commented Oct 6, 2014

The nametuple function creates classes dynamically. The caller must provide the class name thus overriding any existing object name.
An overridden object may be garbage-collected
or survive depending on its reference count.

While this behavior is not new to Python, I am unaware of a simple function with such an awkward side effect.
One might consider this a feature rather than a bug
thus shifting responsibility for carefully passing suitable class names to nametuple.
However, I believe nametuple should raise an exception
if the provided name would override an existing name. If needed, this behavior could be made
customizable by a keyword argument override defaulting to False.

Consequently, the caller would have to delete the object under that
name explicitly before calling nametuple. This behavior would increase code clarity and eliminate´ a source of subtle
errors.

The code example given below shows the survival of
a pre-existing class due to an instance linked to it. As a consequence, two different classes with the same name exist. Only the posterior is,
however, bound to the
__main__ namespace. The prior is no longer known to that namespace potentially breaking
remote parts of the code.

In [1]: from collections import namedtuple

In [2]: AB=namedtuple('AB', ('a','b'))

In [3]: ab=AB(4,9)

In [4]: type(ab)
Out[4]: __main__.AB

In [6]: AB=namedtuple('AB', ('c','d'))

In [7]: type(ab)
Out[7]: __main__.AB

In [8]: ab2=AB(16,25)

In [9]: type(ab2)
Out[9]: __main__.AB

In [10]: type(ab)
Out[10]: __main__.AB

In [11]: ab
Out[11]: AB(a=4, b=9)

In [12]: ab2
Out[12]: AB(c=16, d=25)

@fhaxbox66googlemailcom fhaxbox66googlemailcom mannequin added type-bug An unexpected behavior, bug, or error stdlib Python modules in the Lib dir labels Oct 6, 2014
@mdickinson
Copy link
Member

IMO, this is a horrible idea. I'd hate for creation of a namedtuple class to fail just because there happened to be an existing (perhaps in an as-yet uncollected garbage namedtuple class with the same name). That's the kind of spooky "action at a distance" that makes debugging unnecessarily difficult.

I also think this would be pretty much impossible to implement efficiently. :-)

I'm closing this report here: this behaviour is not a bug, and the suggested exception raising is (IMO) both undesirable and unworkable in practice. I'd suggest opening a thread on the Python mailing-list if you want to discuss the idea further; if that thread produces a focused, widely accepted proposal, feel free to re-open an issue here.

@mdickinson mdickinson added type-feature A feature request or enhancement and removed type-bug An unexpected behavior, bug, or error labels Oct 6, 2014
@vadmium
Copy link
Member

vadmium commented Oct 6, 2014

Perhaps Leo doesn’t understand that the name passed to “namedtuple” is just an indicator for debugging etc, and it doesn’t really have to be unique or even correspond with what it is assigned to. I do remember finding it a bit odd that I had to give it a name when I first used “namedtuple”, but I guess it is because all Python function and class objects store their name internally.

>>> AB = namedtuple("Whatever", ("a", "b"))
>>> AB
<class '__main__.Whatever'>
>>> Whatever
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Whatever' is not defined
>>> Whatever = AB
>>> Whatever
<class '__main__.Whatever'>

@mdickinson
Copy link
Member

Right; the underlying problem of having objects that appear to be instances of the wrong class has nothing to do with namedtuples. After this sequence:

>>> class A: pass
... 
>>> a = A()
>>> 
>>> class A: pass
... 

We get the following somewhat confusing results:

>>> type(a)
<class '__main__.A'>
>>> A
<class '__main__.A'>
>>> isinstance(a, A)
False

Class factories like namedtuple make it somewhat easier to run into this issue, but it's nothing really to do with namedtuple itself, and it's not something that could be "fixed" without significant language redesign.

@fhaxbox66googlemailcom
Copy link
Mannequin Author

fhaxbox66googlemailcom mannequin commented Oct 6, 2014

The idea was based on a misunderstanding of the typename argument. I
had erroneously inferred that the namedtuple class object would be
bound to some namespace whereas the only binding is achieved by the
assignment to a local name which may be different from the typename.
And typename can probably even be an empty string.

I agree that the oddities shown in the two code examples are just an
example of a misuse of the freedom a dynamic language grants.

Rereading the docs on nametuple, I think a clarification on the
purpose and proper use of typename might be in order. Most people have
been declaring classes for many years using the class statement. This
implicitly binds the class name to the current namespace. This is why
I was mislead.

Thanks for the helpful feedback.

Leo

On 06/10/2014, Mark Dickinson <report@bugs.python.org> wrote:
>
> Mark Dickinson added the comment:
>
> Right; the underlying problem of having objects that appear to be instances
> of  the wrong class has nothing to do with namedtuples.  After this
> sequence:
>
>>>> class A: pass
> ...
>>>> a = A()
>>>>
>>>> class A: pass
> ...
>
> We get the following somewhat confusing results:
>
>>>> type(a)
> <class '__main__.A'>
>>>> A
> <class '__main__.A'>
>>>> isinstance(a, A)
> False
>
> Class factories like namedtuple make it somewhat easier to run into this
> issue, but it's nothing really to do with namedtuple itself, and it's not
> something that could be "fixed" without significant language redesign.
>
> 


Python tracker <report@bugs.python.org>
<http://bugs.python.org/issue22563\>


@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants