[Python-ideas] Add kwargs to built-in function object

Calvin Spealman ironfroggy at socialserve.com
Thu May 22 15:43:31 CEST 2008


Start using those and suddenly you are going to have lots of little  
anonymous objects around and you'll start to want to add  
functionality to them and otherwise enforce things about them. Now  
you have a higher barrier than when you would have been creating it  
from scratch.

and remember, object is not a function. It is a type. It is the base  
type of all types and so this has implications beyond what you  
suggest it for. If object(a=10).a == 10, then when custom classes'  
__init__ methods upcall, they'll start to fall back on letting kwargs  
fall up to object.__init__ to set initialization attributes. Now we  
gain this rule of thumb that keyword arguments are probably going to  
end up as attributes, because if we don't 'catch' them and they reach  
object.__init__, they will be. This isn't a behavior the language  
should encourage, because it should be left up to the developer.  
Currently, object.__init__ specifically takes any arguments and does  
nothing with any of them. This is to allow upcall in your __init__  
gracefully, because if the upclass is one of your bases or the final  
base, object, you can still pass your parameters along safely.  
Implying some behavior when it reaches object.__init__, especially  
(in most cases) after you've initialized your object, would probably  
just trounce all over your object and piss you off.

No thanks.

On May 22, 2008, at 3:21 AM, Brandon Mintern wrote:

> I would like to propose to change the built-in function "object" to
> have the following syntax:
>
> object(**kwargs)
> Return a new featureless object. object is a base for all new style
> classes. It has the methods that are common to all instances of new
> style classes.
>
> If kwargs is given, the returned object's __dict__ will be kwargs (or
> something to that effect).
>
>
> An example:
>
> a = object(one=1, two=2)
> a.one # returns 1
> a.two # returns 2
>
>
> The justification:
>
> On several occasions I have needed a collection of attributes to
> represent a single item. When this happens, there are really three
> options:
>
> 1. Use a tuple. This works well for temporarily re-packaging items in
> a loop or for quick-and-dirty code, but it rapidly becomes unreadable
> and hard to maintain. It is not long before you forget what order the
> attributes are in, and at first glance, it is not clear what kind of
> object is being indexed.
>
> 2. Use a dict. This is an improvement over tuples on readability, but
> they can be a pain to build and overly-cumbersome to access later. I
> understand that dicts are used all over the place in Python, but I
> still think of them (in the general case) as a map of keys to values
> where the dict represents a collection, not an object.
>
> 3. Use a class. This requires coming up with a name for the class and
> then writing the class (admittedly, this should be easy). Afterwards,
> this is the most convenient, readable method for representing the
> data, but since it requires non-trivial effort up front, this method
> may be avoided until it's truly apparent that it is necessary.
>
>
> A real-world example:
>
> Let's say that I want to have a map of employee SSNs to employee data.
> I am going to be manipulating this information in various ways, but
> not really in any ways that justify the use of class methods. At any
> rate, let's build this data from a file where each line is
>
> SSN  First  Last  Salary
>
> with the items being whitespace-delimited. The code, then, will be:
>
> employees = {}
> for ssn, first, last, salary in (line.split() for line in open 
> (employee_file)):
>     employees[ssn] = (ssn, first, last, salary) # tuple method
>     employees[ssn] = {"ssn": ssn, "first": first, "last": last,
> "salary": salary} # dict method
>     employees[ssn] = Employee(ssn, first, last, salary) # assumes
> class with proper constructor
>
> # first name of employee with SSN
> employees[SSN][1] # tuple method -- quite unreadable
> employees[SSN]["first"] # dict method -- more readable but sub-optimal
> employees[SSN].first # class method -- readable and simple
>
>
> Now, because of the advantages the class method offers in terms of
> readability, I have written a convenience class that makes using it
> easier:
>
> class Record:
>    """
>    A class intended to provide a simple interface for creating objects
>    with named fields. That is, instead of returning a tuple and  
> indexing
>    it or writing a unique class, you can simply do something like:
>    a = Record(x=1, y=2)
>    a.x # 1
>    a.y # 2
>    a   # Record(x=1, y=2)
>    """
>    def __init__ (self, **kwargs):
>        self.__dict__.update(kwargs)
>
>    def __repr__ (self):
>        return "Record(%s)" \
>               % ", ".join("%s=%s" \
>                           % field for field in  
> self.__dict__.iteritems())
>
> Now, the line in the for loop above becomes
>
>     employees[ssn] = Record(ssn=ssn, first=first, last=last,  
> salary=salary)
>
> and I have completely avoided the need to define a unique class. Note
> that as the number of fields increases, this becomes easier to use
> inline than the dict method, at the same time that it avoids the
> upfront costs of having to build a new class for every distinct type
> of object in the program.
>
> It turns out that other people find such a method useful as well.
> According to Catherine Devlin on the centralOH Python list, it is
> recipe 4.18 from the Python Cookbook (2nd ed.). Several others from
> the mailing list stated that they had created similar solutions
> themselves.
>
> Thus, my suggestion is to simply build such functionality directly
> into the language. While scanning the built-in functions page (I don't
> use any, all, or enumerate nearly enough), I noticed the object()
> function, and since its purpose is to return a featureless object, it
> seems to fit the bill quite well. Adding my suggested functionality
> should break nothing (since the kwargs would be optional) and would
> allow people to stop baking their own solutions to this common
> problem, while getting the speed bonus of a C implementation (if it
> helps).
>
> Thus, the code above becomes
>
> for...
>     employees[ssn] = object(ssn=ssn, first=first, last=last,  
> salary=salary)
>
> employees[SSN].first
>
>
> Does anyone else think this might be a good idea for Python 2.6/3K?
>
> Thanks,
> Brandon
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas




More information about the Python-ideas mailing list