Objects and Classes

What is dir() and how does it differ from __dict__?

In Python, dir() is used to return a list of all attributes and methods of an object. This is a built-in function, and it can be called for any object. Example of dir output:

my_list = [1, 2, 3]
print(dir(my_list))

# ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', 
# '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', 
# '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', 
# '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', 
# '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 
# 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

On the other hand, __dict__ is used to get a dictionary containing the namespace of a class or instance. It can be used to access or modify object attributes.

class MyClass:
    class_attribute = 10
    
    def __init__(self, instance_attribute):
        self.instance_attribute = instance_attribute

my_instance = MyClass(20)

print(MyClass.__dict__)
print(my_instance.__dict__)

# {'__module__': '__main__', 'class_attribute': 10, '__init__': <function MyClass.__init__ at 
# 0x7f84ad1e12f0>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute 
# '__weakref__' of 'MyClass' objects>, '__doc__': None}

# {'instance_attribute': 20}

Can there be attributes without using classes?

In Python, you can define variables outside of classes, but they are not considered class or instance attributes. These are simply global variables that can be accessed from any point in the program. 

It is usually considered good practice to avoid using global variables, as they can make the code difficult to read and debug.

global_variable = 10  # Not an attribute

def test_func():
    global global_variable
    global_variable += 1
    print(global_variable)

test_func()  # Output: 11

What are instance and class attributes?

In Python, class attributes are variables that are defined at the class level and are common to all instances of this class. Access to class attributes is done using the class name, not the instance name:

class MyClass:
    class_attribute = 10

print(MyClass.class_attribute)

You can also access class attributes from a class instance, for example:

example = MyClass()
print(example.class_attribute)  # Output: 10

In this case, Python first looks for the class_attribute attribute in the instance namespace. If it doesn't find it there, it looks for it in the class namespace. You can have both instance attributes and class attributes in Python. Instance attributes are variables specific to each instance of the class, while class attributes are common to all instances of the class.

class MyClass:
    class_attribute = 10

    def __init__(self, instance_attribute):
        self.instance_attribute = instance_attribute

my_instance = MyClass(20)
print(my_instance.class_attribute)      # Output: 10
print(my_instance.instance_attribute)   # Output: 20

What is the difference between methods and functions?

In Python, both functions and methods are used to encapsulate a block of code that can be called multiple times with different input data. However, there is a difference between them:

  1. Functions are separate blocks of code that can be called by name, they can accept input arguments and return output values. In Python, functions can be defined using def, followed by the function name, a list of parameters, and a code block.
    # Example of a simple Python function:
    def add_numbers(x, y):
        return x + y
  2.  Methods are functions associated with objects or classes. In Python, methods are called using dot notation of an object or class and can work with the object's state.
    # my_method is a method of the TestClass class
    class TestClass:
        def my_method(self, username, user_id):
            pass
    

     

A method is any function that is somehow bound to an instance or class. A method can contain the self argument, which accepts a reference to the instance, or contain the cls argument, which accepts a reference to the class. It's also worth adding that even if self or cls is not used, but it is in the class - it's still a method, even if we use @staticmethod and don't preserve the object's state.

Why is it not necessary to inherit from object?

It's worth noting that in Python there are 2 types of class definitions:

  • classic style
  • new style classes

Classes that implicitly inherit from the built-in object class are called new style classes. This is because object is the base class for all new style classes and provides certain functions, such as support for descriptors, properties, and the __slots__ attribute.

The classic style does not inherit from object, this is a feature of the new style. If you refer to TestClass.__bases__ you can see what it inherits from.

class TestClass(int):
    ...

>> TestClass.__bases__
>> (<type 'int'>,)

New style classes introduced the ability to implement property, classmethod, staticmethod, slots, new. That's why they also transitioned to Python3, and that's exactly why everything inherits from object right away.

In Python2, if a class is defined without explicit inheritance from object, it will be an old-style class. Old-style classes have some limitations compared to new-style classes, such as limited support for descriptors, properties, and other additional functions.

What is id() and how does it work at a low level?

The id() function is used to get a unique identifier for an object. The identifier is an integer that is guaranteed to be unique and constant for this object throughout its lifetime.

The function returns the object's memory address in the computer. The memory address is a unique identifier assigned to each object in Python.

a = 10
b = 10

print(id(a))
print(id(b))

# 140172400504848
# 140172400504848

At a low level, id() works by using the object's memory address. In Python, each object is allocated a unique memory address when it's created. The id() function simply returns this memory address as an integer value."

The code snippet demonstrates that two variables with the same value (10) have the same id, which is the memory address where that value is stored.

Comments (0)

Leave a comment