Why "object" is passed as base class in python? - python-3.x

Essentially, what is the difference in defining class using baseclass "object", vs without any baseclass. I have seen classes are defined with baseclass "object" many times.
class MyClass(object):
def __init__(self. *params):
self.params = params
Or,
class MyClass:
def __init__(self. *params):
self.params = params

In Python 3.x, which is the de facto Python language nowadays, there are no differences at all: either have an explicit inheritance from object, or leaving the bases blank is absolutely the same thing.
For Python 2, however it is another matter -
After the language evolved Object Oriented sintaxes with what today are called "classic classes", a series of better features in the inheritance mechanisms, memory allocation, object initialization, attribute retrieval was thought of, and then object was introduced, back in Python 2.2 as the base for what was called "new style classes" in Python 2.x life cycle.
So, if you see some code that is supposed to run in Python 2, not inheriting from object, is almost always an error - which can cause hard to find incorrect behaviors to take place at run time (for example type(instance) will not work properly, you can't use descriptors, such as "properties" and so on).
As stated above, however, all classes in Python 3.0 and above are "new style classes". Explicitly inheriting from object is interesting when one would write code that should run correctly both in Python 2 and Python 3 - few projects today focus on keeping Python 2 compatibility, and that is why one will see less and less "object" as an explicit base in new code.

Related

How can I get deterministic hash values for class objects?

I have an application running in Python 3.9.4 where I store class objects in sets (along with many other kinds of objects). I'm getting non-deterministic behavior even when PYTHONHASHSEED=0 because class objects get non-deterministic hash codes. I assume that's because class objects' hash codes come from their addresses in memory.
For example, here are two runs of a little test program, where Before and Equation are classes:
print(hash(Before), hash(Equation), hash(int))
304555224 304593057 271715397
print(hash(Before), hash(Equation), hash(int))
326601328 293027788 273337413
How can I get Python to generate deterministic hash values for class objects?
Is there a metaclass or something that I could monkey-patch so that all class objects, even int, get a hash function that I specify?
Hash for classes is deterministic within the same process . Yes, in cPython it is memory based - but then you can't simply "move" a class object to another memory address using Python code.
If you happen to use some serialization/de-serialization transforms with the classes, the de-serialized objects will ordinarily be new objects, distinct from the original ones, and therefore will hash differently.
For the note: I could not reproduce the behavior you stated in the question: on the same process, the hashes for the class objects will be the same.
If you are calculating the hashes in different processes, though, the will differ. So, although you don't mention multiprocessing there, I assume that is your working case.
Then, indeed, implementing __hash__ and __eq__ proper methods on the metaclass can allow you a stable, across process, hashing - but you can't do that with built-in classes such as int: those are built in native code and can't be changed on the Python side. On the other hand, despite the hash number shown being different for these built-in classes, whatever you are using to serialize/deserialize your classes (that is what Python does for communicating data across processes, even if you don't do any explicit de/serializing) .
Then we come to, while it is straightforward to add __eq__ and __hash__ methods to a metaclass to your classes, it'd be better to ensure that on deserializing, it would always yield the same object (with the same ID). hash stability, as you put it, could possibly ensure you have always the same class, but it would depend on how you'd write your code: it is a bit tricky to retrieve the object instance that is already inside a set, if you check positively for containship of another instance that matches it - the most straightfoward way would be building a identity-dictionary out of a set, and then use the value:
my_registry_dict = {element: element for element in my_registry_set}
my_class = my_registry_dict[incoming_class]
With this in mind, we can have a custom metaclass that not only add __eq__ and __hash__- and you have to pick what elements of the classes you will want to compare for equality - class.__qualname__ can be a simple and functional attribute to use - but also customize the __new__ method so that upon de-serializing the same class a second time will always re-use the first class object defined in the current process (i.e.: ensuring the "singleton" behavior Python classes enjoy in non-corner cases like yours seems to be)
class Meta(type):
registry = {}
def __new__(mcls, name, bases, namespace):
cls = super().__new__(mcls, name, bases, namespace)
if cls not in mcls.registry:
mcls.registry[cls] = cls
else:
# reuse the previously created class
cls = mcls.registry[cls]
return cls
def __hash__(cls):
# when working with metaclasses, using the name `cls` instead of `self``
# helps reminding us that we are dealing with instances that are
# actually classes.
return hash(cls.__qualname__)
def __eq__(cls, other):
return cls.__qualname__ == other.__qualname__

Python class instance changed during local function variable

Let's for example define a class and a function
class class1(object):
"""description of class"""
pass
def fun2(x,y):
x.test=1;
return x.value+y
then define a class instance and run it as a local variable in the function
z=class1()
z.value=1
fun2(z,y=2)
However, if you try to run the code
z.test
a result 1 would be returned.
That was, though the attribute to x was done inside the fun2() locally, it extended to class instance x globally as well. This seemed to violate the first thing one learn about the python function, the argument stays local unless being defined nonlocal or global.
How could this happen? Why the attribute to class inside a function extend outside the function.
I have even stranger example:
def fun3(a):
b=a
b.append(3)
mya = [1]
fun3(mya)
print(mya)
[1, 3]
>
I "copy" the array to a local variable and when I change it, the global one changes as well.
The problem is that the parameters are not passed by a value (basically as a copy of the values). In python they are passed by reference. In C terminology the function gets a pointer to the memory location. It's much faster that way.
Some languages will not let you to play with private attributes of an instance, but in Python it's your responsibility to make sure that does not happen. One other rule of OOP is that you should change the internal state of an instance just by calling its methods.
But you change the value directly.
Python is very flexible and allows you to do even the bad things. But it does not push you.
I always argue to have always at least vague understanding of the underlaying structure of any higher level language (memory model, how the variables are passed etc.). There is another argument for having some C/C++ knowledge. Most of the higher level languages are written in them or at least are inspired by them. A C++ programmer would see clearly what is going on.

Metaclass of metaclass?

At my OOP theory exam I was asked a question "What is a metaclass? What is a metaclass of metaclass?". I answered first one easily, but have no idea about the second one. Is there even something like "metaclasses of metaclasses" in any programming language, or even theoritically? I tried implementing something like that in Python 3, but it seems it's a bit too complicated for my (I only had simple Python course for 1 semester).
Yes.
I will use the Python language to explain how can that be - maybe it is the language where metaclasses are more palpable (at least it is the language with the majority of questions involving metaclasses here).
So, in an OOP language where "classes" are first class objects - that is, they are themselves objects, and all the rules that apply to other objects apply to classes as well - they just happen to be the "template" for other kind of objects, these classes themselves are instances of "something". This something is the "metaclass" - which is just a word to designate the "class of a class".
And it happens that this "metaclass", the class of a class is an object as well, just as other classes. And as such, it also is an instance of a class - this class of the metaclass is what can be named the "metametaclass".
Now, bringing it down to a concrete example in Python - by default, the metaclass for classes in Python is type. That is, type is the class which instances are classes.
The language does have ingenious mechanisms that make it practical in some points to inherit a class from type, and then work with custom meta-classes.
So, what is the class of type? That will be the "metametaclass" for most (or all) classes in Python.
And as it goes, the class of "type" is "type" itself. yes - it is a circular reference, without which the object hierarchy of the language could not be bootstraped. I don't know if other languages do that differently - but in Python it is quite patent:
>>> class A:
... pass
...
>>> type(A)
<class 'type'>
>>> type(type(A))
<class 'type'>
>>> type(type(A)) is type(A)
True
Now, besides working like that as a concept, it actually can be used as a metametaclass, and there are mechanisms of the language that can be tweaked by inheriting type for that purpose. (Normally it will be inherited to be customized as an "ordinary" metaclass).
By coincidence, I had an use case for the "metametaclass" exemplified this very week, in a question here - by customizing Python's type __call__ method, instead of __new__ or __init__, and using this custom class as the "metaclass for a metaclass" one can actually control how those methods are called and the parameters passed to them methods when an ordinary class is be created.

PyQt5: Set Central Widget [duplicate]

I am a self-taught python user (kind of.). I read much to deepen my knowledge about python. Today
I encountered a text saying:
... classes and objects ....
So I was wondering what is the difference between objects and classes in python. I taught all classes are objects, but in that case, author wouldn't have used phrase "classes and objects". I'm confused...
These are two closely related terms in object oriented programming. The standard meaning is that an object is an instance of a class.
An object is an instantiation of a class.
Think of a class like the blueprint of a car.
Ford make cars (objects) based on the rules and information enclosed in the blueprint.
Yes, classes (and functions, and modules, and basically everything) in Python are objects, too. The difference lies in their types:
class Foo(object): pass
print type(Foo)
print type(Foo())
To see they're both objects, you can check that they both have attributes:
print dir(Foo)
print dir(Foo())
A class describes what that object will be, but it isn't the object itself.
A class is an idea. An object is the fruition of that idea.

Using a class vs just functions [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am going to be creating a script that parses through an XML (very large, .5gb+), and am trying to think of how to efficiently do it.
Normally, I would do this in AutoIt, as that's my 'normal' language to use for things, but I think it's more appropriate to do it in Python (plus I'd like to learn more python).
Normally how I'd do this, is create a constant with all the 'columns' I'd need from the XML, use that to match and parse it through into an array (actually 2 arrays, cause of subrecords), then pass sets of the array(s) to the system of record as JSON objects/strings.
In Python, I'm not sure that's the best route. I was thinking about making a class of the object, then creating instances for each record/row of the XML that I'd convert to JSON and then submit. If I feel ambitious, I'd even work on getting it to be multithreaded. My best option would be to pull out a record, then submit it in the background while I work on the next record, up to say, 5 to 10 records, but perhaps that's not good.
My question is, does it seem like I'm using a class just to use a class, or does it seem like a good reason to do it? I admit my thinking is colored by the fact that I haven't used classes much (at all) before, and am using it because it's neat and new.
Is there actually a totally better way that I'm overlooking because I'm blinded by new/shiny concepts, or lack of knowledge of the program (this is probably likely to me)?
I'm hoping for answers that will guide me in a general direction - this is part of my learning the language and doing the research myself really helps me understand what I'm doing and why. Unfortunately, I think I need a guide here on this point.
This debate is largely situational in nature, and will depend on what you intend to do within your program. The main thing I would consider is, Do I need to encapsulate properties (data) and functionality(methods/functions) into a single grouping?
Some additional things that come to mind, in terms of pros vs. cons of using a class (object) in this context:
Reasons to use a class:
If potential future maintainability would warrant 'swapping' in a new class into an existing structure within the program.
If there are attributes that would hold true for all instances of the class.
If it makes logical sense to have a group of functions separated out from the rest of your program.
More concise options for ensuring immutability
Providing a type for the underlying fields meshes well with the rest of your program.
Reasons not to use a class:
The code can be maintained purely through the addition of new functions.
You aren't performing functional tasks on the fields stored (e.g. storing create_date, but needing only to work with age - this can lend itself better to an object that doesn't expose create_date, but rather just a function get_age).
You have severe performance optimization standards to meet and can't justify calls to functions to ensure encapsulation, any additional memory overhead, etc...
Generally, Python lends itself to using classes since it is an object-oriented language. However, compared to more heavily oop languages like C++ and Java, you can "get away" with a lot more in Python without using classes. If you want to explore using a class, I certainly think it would be a good exercise in use of the language.
Edit:
Based on follow-up comment, I wanted to provide an example of using named arguments to instantiate a class with optional fields. The general overview, is that Python interprets the ordering of arguments when considering which argument to assign to internal functionality. As an example:
def get_info(name, birthday, favorite_color):
age = current_time - birthday
return [name, age, favorite_color]
In this example, Python interprets the input arguments based on the order they appear when the method is called:
get_info('James', '03-05-1998', 'blue')
However, Python also allows for named arguments, which specify the parameter-internal field assignment explicitly:
get_info(name='James', birthday='03-05-1998', favorite_color='blue')
While at first glance this syntax appears to be more verbose, it actually allows for great flexibility, in that ordering of named arguments doesn't matter, and you can set defaults for arguments that aren't passed into the method's signature:
def get_info(name, birthday, favorite_color=None):
age = current_time - birthday
return [name, age, favorite_color]
get_info(name='James', birthday='03-05-1998')
Below I've provided a more in-depth working example of how named arguments could help the situation you've outlined in your comment (Many fields, not all of them required) Play around with constructing this object in various ways to see how the non-named parameters are required, but the named parameters are optional and will default to the values specified in the __init__() method:
class Car(object):
""" Initializes a new Car object. Requires a color, make, model, horsepower, price, and condition.
Optional parameters include: wheel_size, moon_roof, premium_sound, interior_color, and interior_material."""
def __init__(self, color, make, model, horsepower, price, condition, wheel_size=16, moon_roof=None, premium_sound=None, interior_color='black', interior_material='cloth'):
self.color = color
self.make = make
self.model = model
self.horsepower = horsepower
self.price = price
self.condition = condition
self.wheel_size = wheel_size
self.moon_roof = moon_roof
self.premium_sound = premium_sound
self.interior_color = interior_color
self.interior_material = interior_material
# Prints attributes of the Car class and their associated values in no specific order.
def print_car(self):
fields = []
for key, value in self.__dict__.iteritems():
fields.append(key + ': ')
fields.append(str(value))
fields.append('\n')
print ''.join(fields)
# Executes the main program body
def main():
stock_car = Car('Red', 'Honda', 'NSX', 290, 89000.00, 'New')
stock_car.print_car()
custom_car = Car('Black', 'Mitsubishi', 'Lancer Evolution', 280, 45000.00, 'New', 17, "Tinted Moonroof", "Bose", "Black/Red", "Suede/Leather")
custom_car.print_car()
# Calls main() as the entry point for this program.
if __name__ == '__main__':
main()

Resources