The Path to Learning Python – Jin Yong’s Martial Arts Edition Part Two: ‘Eighteen Dragon-Subduing Palms’ (Advanced Part – 2)

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)The Path to Learning Python – Jin Yong’s Martial Arts Edition Part Two: ‘Eighteen Dragon-Subduing Palms’ (Advanced Part – 1)

If you like it, pleasefollowme

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)Eighteen Dragon-Subduing Palms (Powerful and profound, requires a foundation in internal strength)Object-Oriented Advanced03Seeing the Dragon in the FieldThe Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Built-in Functions

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)[callable]Determines if a value is executable

def func():   
    pass

callable(func) # True


class Foo:   
    def __call__(self, *args, **kwargs):     
        pass


obj = Foo() 
callable(obj) # True


"""
If in future development, when encountering the following code,
one can know that the handler parameter:
may be a [function][class][object (including __call__ method)]
"""
def send_msg(handler):   
    handler()

[super]Searches for specified members according to the inheritance relationship

class Base:   
    def message(self, num):     
        print("Base.message", num) 

class Foo(Base):   
    def message(self, num):     
        print("Foo.message", num) 
        super().message(num + 100) # Calls the message method in the parent class
  • self: First looks in the current class, then goes to the parent class;
  • super: Directly looks in the parent class;

[type]Gets the type of an object

class Foo:   
    pass

obj = Foo() 
type(obj) == Foo # True

[isinstance]Determines if an object is an instance of a certain class or subclass

class Top:   
    pass

class Base(Top):   
    pass

class Foo(Base):   
    pass

obj = Foo() 
isinstance(obj, Foo) # True obj is an instance of Foo class 
isinstance(obj, Base) # True obj is an instance of Base class 
isinstance(obj, Top) # True obj is an instance of Top class

[issubclass]Determines if the current class is a subclass of a certain class

class Top:   
    pass

class Base(Top):   
    pass

class Foo(Base):   
    pass

issubclass(Foo, Base) # True 
issubclass(Foo, Top) # True

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Exception Handling

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)Exception Handling Syntax

  • Exception Handling Syntax One
    try: 
        pass
    except Exception as e: 
        pass
  • Exception Handling Syntax Two
    try: 
        pass
    except Exception as e: 
        pass
    finally: 
        pass

Common Exception Categories

  • AttributeError – Attempting to access an attribute that an object does not have
  • IOError – Input/Output exception, basically unable to open a file
  • ImportError – Unable to import a module or package, basically a path issue or name error
  • IndentationError – Syntax error (subclass), code not properly aligned, etc.
  • IndexError – Index out of range
  • KeyError – Attempting to access a key that does not exist in a dictionary
  • KeyboardInterrupt – Ctrl+C was pressed
  • NameError – Using a variable that has not yet been assigned an object
  • SyntaxError – Syntax error
  • TypeError – The type of the object passed does not match the requirement
  • UnboundLocalError – Attempting to access a local variable that has not yet been set, basically due to another global variable with the same name, leading you to think you are accessing it
  • ValueError – Passing a value that the caller does not expect, even if the type of the value is correct

Custom Exception

class MyException(Exception): 
    def __init__(self, msg, *args, **kwargs): 
        super().__init__(*args, **kwargs) 
        self.msg = msg

raise to throw an exception

try: 
    xxx 
    if xxx: 
        raise MyException() # Trigger custom exception 
except MyException as e: 
    pass

finally

def func():   
    try: 
        return 123   
    except Exception as e: 
        pass   
    finally: 
        print(666) 

func() # 666

04Dragon Tail SwingThe Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Reflection

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)[Reflection] can achieve: operating members in an object (performing operations on members of the object in the form of strings)Built-in Functions (Reflection)[getattr]

val1 = getattr(object, "member_name") # Returns None when the specified member does not exist

val2 = getattr(object, "member_name", default_value_if_not_exist[None])

[setattr]

setattr(object, "member_name", value)

[hasattr]

result = hasattr(object, "member_name") # Returns True/False

[delattr]

delattr(object, "member_name")

[import_module + Reflection]

# Import module 
from importlib import import_module 

m = import_module("requests.exceptions") # Import module 

cls = getattr(m, "InvalidURL") # Get class from module

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Read-Only Fields

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)Data Class

from dataclasses import dataclass, InitVar 

@dataclass 
class Data:   
    readonly_field: str # Read-only field 
    writable_field: str # Writable field 
    _initialized: InitVar[bool] = False # Initialization flag 

    def __post_init__(self, _initialized):     
        self._initialized = True    

    def __setattr__(self, key, value):     
        # After initialization, prohibit modification of read-only fields 
        if hasattr(self, '_initialized') and self._initialized and key == 'readonly_field': 
            raise AttributeError(f"'{type(self).__name__}' object attribute '{key}' is read-only") 
        super().__setattr__(key, value)
d = Data(readonly_field="Read-Only", writable_field="Writable") 

d.writable_field = "Modified Value"  # Allowed to modify 
d.readonly_field = "Attempt to Modify"  # Error: AttributeError

Regular Class (Recommended)

class Data: 
    def __init__(self, readonly_value: str, writable_value: str): 
        self._readonly = readonly_value # Private read-only attribute 
        self.writable = writable_value # Public writable attribute 

    @property 
    def readonly(self) -> str:     
        return self._readonly 

    @readonly.setter 
    def readonly(self, value): 
        raise AttributeError("Attribute is read-only, modification prohibited")
d = Data(readonly_value="Read-Only", writable_value="Writable") 
print(d.readonly) # Access read-only attribute 
d.writable = "Modified Value"  

# Allowed to modify 
d.readonly = "Attempt to Modify"  # Error: AttributeError

Metaclass

class ReadOnlyDescriptor:   
    def __init__(self, field_name):     
        self.field_name = field_name 

    def __get__(self, instance, owner):     
        if instance is None: 
           return self 
        return instance.__dict__[self.field_name] 

    def __set__(self, instance, value):     
        raise AttributeError(f"Attribute '{self.field_name}' is read-only") 


class ReadOnlyMeta(type):   
    def __new__(cls, name, bases, attrs):     
        readonly_fields = attrs.pop('__readonly_fields__', []) 
        new_attrs = {} 
        for attr_name, attr_value in attrs.items(): 
            if attr_name in readonly_fields: 
                new_attrs[attr_name] = ReadOnlyDescriptor(attr_name) 
            else: 
                new_attrs[attr_name] = attr_value 
        return super().__new__(cls, name, bases, new_attrs) 


class Data(metaclass=ReadOnlyMeta):   
    __readonly_fields__ = ['readonly'] # Specify read-only fields 

    def __init__(self, readonly, writable):     
        self.readonly = readonly 
        self.writable = writable
d = Data(readonly="Read-Only", writable="Writable") 

d.writable = "Modified"  # Allowed 
d.readonly = "Attempt to Modify"  # Error: AttributeError

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Advanced Part – Conclusion

The Path to Learning Python - Jin Yong's Martial Arts Edition Part Two: 'Eighteen Dragon-Subduing Palms' (Advanced Part - 2)

Leave a Comment