Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion Lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,27 @@ def _m(self): pass

# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
"""Create a class object dynamically using the appropriate metaclass."""
"""Create a class object dynamically using the appropriate metaclass.

Arguments:
name -- the new class name
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indent the argument list.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to do it just like in PEP 257 which doesn't have indentation. But I'll indent next time.

bases -- sequence of parent classes (default ())
kwds -- mapping of keyword arguments to be supplied to parents' `__init_subclass__`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not only passed to __init_subclass__, it will be passed also to __prepare__ of the computed metaclass, to the metaclass call itself, and in future to any other place required by the class creation machinery. This sentence should be reformulated to something simpler but correct, like mapping of keyword arguments in an equivalent class statement (see example below).

exec_body -- a callback used to populate the freshly created class namespace

Note: the class-creation functionality of `new_class` is similar to `type`. However,
calls to `type` cannot be directly substituted by calls to `new_class`. For example:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although, you were hit but this particular problem, I don't think it deserves a dedicated note. Just describing clearly every argument is enough. Plus maybe an example of usage like this:

For example, the class definition::

    class C(A, B, foo=bar):
        x = 42

can be translated to the following call to `new_class`::

    C = new_class('C', (A, B), {'foo': bar}, lambda ns: ns.update(x=42))


type("MyClass", (), dict(my_method=lambda self: None))

...is not equivalent to the below, which will produce a `TypeError`:

new_class("MyClass", (), dict(my_method=lambda self: None))

Instead, the correct way to use `new_class` in this instance is:

new_class("MyClass", (), {}, lambda ns: ns.update(dict(my_method=lambda self: None)))
"""
resolved_bases = resolve_bases(bases)
meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
if exec_body is not None:
Expand Down