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?
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 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.
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.
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.
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__'
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With