Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Python's empty classes and functions work as arbitrary data containers, but not other objects?

Tags:

python

I've seen two different Python objects used to group arbitrary data together: empty classes and functions.

def struct():
    pass

record = struct
record.number = 3
record.name = "Zoe"


class Struct:
    pass

record = Struct()
record.number = 3
record.name = "Zoe"

Even if the class isn't empty, it seems to work so long as it's defined at runtime.

But when I got cocky and tried to do this with built-in functions or classes, it didn't work.

record = set()
record.number = 3
AttributeError: 'set' object has no attribute 'number'

record = pow
pow.number = 3
AttributeError: 'builtin_function_or_method' object has no attribute 'number'

Is there a fundamental difference between built-in and "custom" classes and functions that accounts for this behavior?

like image 240
Eli Rose Avatar asked Jul 11 '13 13:07

Eli Rose


People also ask

What is the use of empty class in Python?

In Python, to write an empty class pass statement is used. pass is a special statement in Python that does nothing. It only works as a dummy statement. However, objects of an empty class can also be created.

What is the purpose of containers in Python?

What are Containers or Collection Types? In many cases, we will want to store many values into a single variable, known as a container or a collection. These containers can hold an arbitrary number of other objects. There are a number of common containers present in Python so let's dive right in.

What are container objects in Python?

Containers are any object that holds an arbitrary number of other objects. Generally, containers provide a way to access the contained objects and to iterate over them. Examples of containers include tuple , list , set , dict ; these are the built-in containers.

How do classes work in Python?

Python classes provide all the standard features of Object Oriented Programming: the class inheritance mechanism allows multiple base classes, a derived class can override any methods of its base class or classes, and a method can call the method of a base class with the same name.


2 Answers

The difference is that both function objects and your Struct object have a __dict__ attribute, but set instances and built-in functions do not:

>>> def struct():
...     pass
...
>>> record = struct
>>> record.number = 2
>>> struct.__dict__
{'number': 2}
>>> class Struct:
...     pass
...
>>> record = Struct()
>>> record.number = 3
>>> record.__dict__
{'number': 3}
>>> record=set()
>>> record.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'set' object has no attribute '__dict__'
>>> pow.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute '__dict__'

In classes you can emulate the behavour using slots (although only on new-style classes):

>>> class StructWithSlots(object):
...     __slots__ = []
...
>>> record = StructWithSlots()
>>> record.number = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'StructWithSlots' object has no attribute 'number'
>>> record.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'StructWithSlots' object has no attribute '__dict__'
like image 136
RoadieRich Avatar answered Nov 28 '22 11:11

RoadieRich


Built-in types are written in C and cannot be modified like that. But after the type/class unification introduced in py2.2 you can now inherit from a built-in types and override or add your own attributes to that subclass.

You can use the forbiddenfood package to add attributes to built-in types:

This project aims to give you the way to find heaven in tests, but it might lead you to hell if you use it on production code.

>>> from forbiddenfruit import curse 
>>> def words_of_wisdom(self):
 ...     return self * "blah "
>>> curse(int, "words_of_wisdom", words_of_wisdom)
>>> assert (2).words_of_wisdom() == "blah blah "

And of course if you're cocky enough then you can create your own types in C and add such features to it.

like image 30
Ashwini Chaudhary Avatar answered Nov 28 '22 11:11

Ashwini Chaudhary