How to create an object with built-in "object()" in Python? - python

I found there is object() which is a built-in function in Python. *You can find object() in Built-in Functions
And, the documentation says below:
Return a new featureless object. object is a base for all classes. It
has methods that are common to all instances of Python classes. This
function does not accept any arguments.
As the documentation says, object() can create an object but I don't know how to do it.
My questions:
How to create an object with object()?
When to use object()? or What are the use cases of object()?

To create an object with object, just call it: object(). However, it is never (as noted in the comments, it may be sometimes useful, when you need to have a something but you don't care what it is) used as is. object is just the (implicit in Python 3) base class of all classes. It provides basic features, such as allocation and magic methods, that you never directly manipulate in Python.
The naming follows one of Python's catchphrases "everything is an object".

You can create an object with only object() as shown below:
print(type(object()))
Then,the object of object class is created:
<class 'object'>
In addition, you can create and initialize the object of Person class with object() as shown below:
class Person:
def __init__(self, name):
self.name = name
obj = object().__new__(Person) # Creates the object of "Person" class
print(type(obj))
obj.__init__("John") # Initializes the object of "Person" class
print(obj.name)
Then, the object of Person class is created and initialized:
<class '__main__.Person'>
John

Related

Getting private attribute in parent class using super(), outside of a method

I have a class with a private constant _BAR = object().
In a child class, outside of a method (no access to self), I want to refer to _BAR.
Here is a contrived example:
class Foo:
_BAR = object()
def __init__(self, bar: object = _BAR):
...
class DFoo(Foo):
"""Child class where I want to access private class variable from parent."""
def __init__(self, baz: object = super()._BAR):
super().__init__(baz)
Unfortunately, this doesn't work. One gets an error: RuntimeError: super(): no arguments
Is there a way to use super outside of a method to get a parent class attribute?
The workaround is to use Foo._BAR, I am wondering though if one can use super to solve this problem.
Inside of DFoo, you cannot refer to Foo._BAR without referring to Foo. Python variables are searched in the local, enclosing, global and built-in scopes (and in this order, it is the so called LEGB rule) and _BAR is not present in any of them.
Let's ignore an explicit Foo._BAR.
Further, it gets inherited: DFoo._BAR will be looked up first in DFoo, and when not found, in Foo.
What other means are there to get the Foo reference? Foo is a base class of DFoo. Can we use this relationship? Yes and no. Yes at execution time and no at definition time.
The problem is when the DFoo is being defined, it does not exist yet. We have no start point to start following the inheritance chain. This rules out an indirect reference (DFoo -> Foo) in a def method(self, ....): line and in a class attribute _DBAR = _BAR.
It is possible to work around this limitation using a class decorator. Define the class and then modify it:
def deco(cls):
cls._BAR = cls.__mro__[1]._BAR * 2 # __mro__[0] is the class itself
return cls
class Foo:
_BAR = 10
#deco
class DFoo(Foo):
pass
print(Foo._BAR, DFoo._BAR) # 10 20
Similar effect can be achieved with a metaclass.
The last option to get a reference to Foo is at execution time. We have the object self, its type is DFoo, and its parent type is Foo and there exists the _BAR. The well known super() is a shortcut to get the parent.
I have assumed only one base class for simplicity. If there were several base classes, super() returns only one of them. The example class decorator does the same. To understand how several bases are sorted to a sequence, see how the MRO works (Method Resolution Order).
My final thought is that I could not think up a use-case where such access as in the question would be required.
Short answer: you can't !
I'm not going into much details about super class itself here. (I've written a pure Python implementation in this gist if you like to read.)
But now let's see how we can call super:
1- Without arguments:
From PEP 3135:
This PEP proposes syntactic sugar for use of the super type to
automatically construct instances of the super type binding to the
class that a method was defined in, and the instance (or class object
for classmethods) that the method is currently acting upon.
The new syntax:
super()
is equivalent to:
super(__class__, <firstarg>)
...and <firstarg> is the first parameter of the method
So this is not an option because you don't have access to the "instance".
(Body of the function/methods is not executed unless it gets called, so no problem if DFoo doesn't exist yet inside the method definition)
2- super(type, instance)
From documentation:
The zero argument form only works inside a class definition, as the
compiler fills in the necessary details to correctly retrieve the
class being defined, as well as accessing the current instance for
ordinary methods.
What were those necessary details mentioned above? A "type" and A "instance":
We can't pass neither "instance" nor "type" which is DFoo here. The first one is because it's not inside the method so we don't have access to instance(self). Second one is DFoo itself. By the time the body of the DFoo class is being executed there is no reference to DFoo, it doesn't exist yet. The body of the class is executed inside a namespace which is a dictionary. After that a new instance of type type which is here named DFoo is created using that populated dictionary and added to the global namespaces. That's what class keyword roughly does in its simple form.
3- super(type, type):
If the second argument is a type, issubclass(type2, type) must be
true
Same reason mentioned in above about accessing the DFoo.
4- super(type):
If the second argument is omitted, the super object returned is
unbound.
If you have an unbound super object you can't do lookup(unless for the super object's attributes itself). Remember super() object is a descriptor. You can turn an unbound object to a bound object by calling __get__ and passing the instance:
class A:
a = 1
class B(A):
pass
class C(B):
sup = super(B)
try:
sup.a
except AttributeError as e:
print(e) # 'super' object has no attribute 'a'
obj = C()
print(obj.sup.a) # 1
obj.sup automatically calls the __get__.
And again same reason about accessing DFoo type mentioned above, nothing changed. Just added for records. These are the ways how we can call super.

How to make a parent class object referring to a child class?

Like in java or C# where we can create an object like
Account obj = new SavingsAccount();
where Account is the parent class and SavingsAccount is the child class
How do I do the same thing with python?
basically I'm trying to do is this
https://repl.it/#MushfiqurRahma1/Polymorphic-Object
Python is dynamically typed: names refer to objects without any notion of type being involved. You just have
>>> class Account: pass
...
>>> class SavingsAccount(Account): pass
...
>>> obj = SavingsAccount()
Each object stores a reference to its own type
>>> type(obj)
<class '__main__.SavingsAccount'>
and each type has a referent to its method resolution order (MRO)
>>> type(obj).__mro__
(<class '__main__.SavingsAccount'>, <class '__main__.Account'>, <class 'object'>)
Instance attributes are not "compartmentalized" according to the class that "defines" them; each attribute simply exists on the instance itself, without reference to any particular class.
Methods exist solely in the classes themselves; when it comes time to call obj.foo(), the MRO is used to determine whose definition is used.
Python uses Duck typing, which means you shouldn’t really care about the class in the Left side of the assignment. Just instantiate the Child class and you should already be able to use it’s parent “interface” to do stuff like dynamic method calls.
Python is a loosely typed language. That means you don't have to specify your variable types. You could just do something like:
class Account():
def deposit():
pass
class SavingsAccount(Account):
pass
obj = SavingsAccount()
obj.deposit(20)
EDIT: As chepner pointed out: Python is strongly typed, but also dynamically typed: type is associated with an object, not the name referring to an object.

Questions related to classes

I have a problem understanding some concepts of data structures in Python, in the following code.
class Stack(object): #1
def __init__(self): #2
self.items=[]
def isEmpty(self):
return self.items ==[]
def push(self,item):
self.items.append(item)
def pop(self):
self.items.pop()
def peak(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s = Stack()
s.push(3)
s.push(7)
print(s.peak())
print (s.size())
s.pop()
print (s.size())
print (s.isEmpty())
I don't understand what is this object argument
I replaced it with (obj) and it generated an error, why?
I tried to remove it and it worked perfectly, why?
Why do I have __init__ to set a constructor?
self is an argument, but how does it get passed? and which object does it represent, the class it self?
Thanks.
object is a class, from which class Stack inherits. There is no
class obj, hence error. However, you can define a class that does
not inherit from anything (at least, in Python 2).
self represents an object on which the method is called; for
example when you do s.pop(), self inside method pop refers to
the same object as s - it is not a class, it is an instance of the class.
1
object here is the class your new class inherits from. There is already a base class named object, but there is no class named obj which is why replacing object with obj would cause an error. Anyway in your example code it is not needed at all since all classes in python 3 implicitly extends the object class.
2
__init__ is the constructor of the object and self there represents the object that you are creating itself, not the class, just like in the other methods you made.
Point 1:
Some history required here... Originally Python had two distinct kind of types, those implemented in C (whether in the stdlib or C extensions) and those implemented in Python with the class statement. Python 2.2 introduced a new object model (known as "new-style classes") to unify both, but kept the "classic" (aka "old-style") model for compatibility. This new model also introduced quite a lot of goodies like support for computed attributes, cooperative super calls via the super() object, metaclasses etc, all of which coming from the builtin object base class.
So in Python 2.2.x to 2.7.x, you can either create a new-style class by inheriting from object (or any subclass of object) or an old-style one by not inheriting from object (nor - obviously - any subclass of object).
In Python 2.7., since your example Stack class does not use any feature of the new object model, it works as well as an 'old-style' or as a 'new-style' class, but try to add a custom metaclass or a computed attribute and it will break in one way or another.
Python 3 totally removed old-style classes support and object is the defaut base class if you dont explicitely specify one, so whatever you do your class WILL inherit from object and will work as well with or without explicit parent class.
You can read this for more details.
Point 2.1 - I'm not sure I understand the question actually, but anyway:
In Python, objects are not fixed C-struct-like structures with a fixed set of attributes, but dict-like mappings (well there are exceptions but let's ignore them for the moment). The set of attributes of an object is composed of the class attributes (methods mainly but really any name defined at the class level) that are shared between all instances of the class, and instance attributes (belonging to a single instance) which are stored in the instance's __dict__. This imply that you dont define the instance attributes set at the class level (like in Java or C++ etc), but set them on the instance itself.
The __init__ method is there so you can make sure each instance is initialised with the desired set of attributes. It's kind of an equivalent of a Java constructor, but instead of being only used to pass arguments at instanciation, it's also responsible for defining the set of instance attributes for your class (which you would, in Java, define at the class level).
Point 2.2 : self is the current instance of the class (the instance on which the method is called), so if s is an instance of your Stack class, s.push(42) is equivalent to Stack.push(s, 42).
Note that the argument doesn't have to be called self (which is only a convention, albeit a very strong one), the important part is that it's the first argument.
How s get passed as self when calling s.push(42) is a bit intricate at first but an interesting example of how to use a small feature set to build a larger one. You can find a detailed explanation of the whole mechanism here, so I wont bother reposting it here.

Python style with attributes in class definition

I have a class with some attributes I want to use the methods. What is the most pythonic way to use it?. Is there documentation I can read about these styles issues?. I use pylint and pep8 to fix this kind of issues, but these program don't show any errors in this example with the attribute
class A(object):
BLOCK_SIZE = 8192
def func1(self):
print self.BLOCK_SIZE
def func2(self):
print A.BLOCK_SIZE
If I understand correctly this two case are the same, but I don't
know if is better to refer the class name or use the self reference.
Thanks
You should prefer self.
There are two types of fields - Class variables and Object variables.
Class variables are shared in the sense that they are accessed by all objects (instances) of that class. There is only copy of the class variable and when any one object makes a change to a class variable, the change is reflected in all the other instances as well.
Object variables are owned by each individual object/instance of the class. In this case, each object has its own copy of the field i.e. they are not shared and are not related in any way to the field by the same name in a different instance of the same class.
By using A.BLOCK_SIZE - you get class variable while by using self.BLOCK_SIZE you get an attribute of the specific object.
Check this to get a detailed example and explanations.
https://www.ibiblio.org/g2swap/byteofpython/read/class-and-object-vars.html
A class attribute can more or less be used as the default value for an instance attribute. The language allow a class attribute to be read either from the class itself or from any instance of the class, provided the instance has no attribute of same name.
But things go differently for write access: A.BLOCK_SIZE=16384 will change the global class attribute, while self.BLOCK_SIZE=16384 will create (or update) an instance attribute of same name.
Here is a little example with your class:
>>> a = A()
>>> a.func1() # access the class attribute
8192
>>> a.func2() # access the class attribute too
8192
>>> a.BLOCK_SIZE=4096 # create an instance attribute of same name
>>> a.func1() # access the INSTANCE attribute
4096
>>> a.func2() # still access the class attribute
8192
That's the reason why you should under common circonstances use the instance semantics (self.BLOCK_SIZE) because it does not rely on the class name and allows per instance override.
The class semantics A.BLOCK_SIZE should only be used if you want to change the class attribute, or need to use the class attribute even if an instance attribute exists.

python metaclass,type class and the object class

I'm having headache trying to understand the cyclic relationship that exit between the metaclass type, the object class, and the class type.
I'm trying to understand how python makes everything an object.is it because everything is an instance of the metaclass type or is it because everything is a subclass of object class.
if its because of being subclass of object class, does that mean if the class object was named class pyobj. Would that mean that everything in Python starts with pyobj?
I know objects created by metaclass are types/classes, this types are then used to create other object.
From this:
>>> isinstance(type, object)
True
>>> isinstance(object,type)
True
>>> issubclass(object,type)
False
>>> issubclass(type,object)
True
Is it safe to say that python creates the class object first using the type metaclass (I'm simplifying the metaclass for brevity).
type('object',(),{})
which implies class object is a class of class type and it does not inherit any attributes other class.
Then it creates the class type:
type('type', (object,),{})
implying type class is class of class type and it inherits attributes from the object class.
Then creates the other classes by inheriting from the class object
type('dict', (object,), {})
type('Animal', (object), {})
which similar to creating an Animal class as :
class Animal:
pass
Does this mean the metaclass used to create the class object is still the one used to create this Animal class or is the metaclass type used by default ?
Which type is being used, is it the metaclass type or the type class that was created after object was created ?
Where does the class type created with the base class object come into play ?
I have also tried to understand what really is going on between the object and the class from all he responses above and in this article http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html
I'm still getting confused. What is the relation between this two class in terms of object creation?
Will I ever get this or is it a chicken and egg situation?
Python's core types really do have a chicken and egg situation going on. type inherits from object, but object is an instance of type.
You can't really reason about which of object or type is defined first in Python, because in regular Python code you could not set up their relationship. The Python interpreter gets to do it by fiddling with the internals before the environment is set up, so it doesn't matter if the types are not completely defined up front.
In your example where you call type to create new object and type types, you're not actually getting objects that are equivalent to the real type and object, as your new object type is an instance of the builtin type metaclass, not the hand-made type metaclass you create later.
Here's an illustration of roughly how the interpreter goes about it. The code doesn't actually work, since you can't create a new-style class without inheriting from object, nor can you reassign a type object's __class__ attribute (to make object an instance of type). If you could, you could start up your own independent type system!
my_object = type('my_object', (), {}) # this doesn't work right, it inherits from object
my_type = type('my_type', (my_object,), {})
my_object.__class__ = my_type # this doesn't work at all (it will raise an exception)

Categories