• python several confusing magic methods


    magic methods

    https://www.educba.com/python-magic-method/?msclkid=8119e878ce8511ec9d52cc88840aaf9b

    魔法方法是一组预定义的功能方法,一般不需要程序员关注,所以称为魔法方法, 这里翻译成 神秘方法,更加合适。

    Magic methods are a collection of pre-defined functional method from the python library functions that cannot be declared or called directly. Instead, these functions can be called or invoked by executing some other related code snippet methods. This type of methods are simple to use and implement, as it does not require specific or any kind of extra manual effort from the programmer. Hence it is named as the ‘Magic Method’.

    What is Python Magic Method?

    • Python is an interpreted, object-oriented programming that gives you the ability to write procedural code and/or object-oriented as we know that creating Objects simplifies complicated data structures handling. In addition to that, magic methods eases the ability to create object-oriented programming.
    • Before Diving into a magic method, let’s understand why they are created in the first place, they are created?
    • Below is one example of class one using a magic method and the other is without the magic method. In the first one __init__ magic method is used, which can be used to initialize more than one instance variable in one go. A class Sports is defined as taking two instance variables into account that is name and sport.
    • Both instance variables can be defined in one go using the __inti__ magic method. In case 2, the same thing is repeated, but this time we are using a set method to initialize the instance variable. Here for 2 variables, we have to call this method twice.

    https://www.geeksforgeeks.org/dunder-magic-methods-python/?msclkid=8119c107ce8511eca07df1a2100f52f8

    魔法方法带有两个下划线作为前后缀。

    如果程序员需要使用的话,需要在定义的子类中做重载。

    最常用的是 对象初始化方法 __init__

    Dunder or magic methods in Python are the methods having two prefix and suffix underscores in the method name. Dunder here means “Double Under (Underscores)”. These are commonly used for operator overloading. Few examples for magic methods are: __init__, __add__, __len__, __repr__ etc.

    The __init__ method for initialization is invoked without any call, when an instance of a class is created, like constructors in certain other programming languages such as C++, Java, C#, PHP etc. These methods are the reason we can add two strings with ‘+’ operator without any explicit typecasting.

    https://www.cnblogs.com/lightsong/p/15974345.html

    __new__ 方法一般用于元类生成一般类场景。

    class Meta(type):
        def __new__(cls, name, bases, dct):
            x = super().__new__(cls, name, bases, dct)
            x.attr = 100
            return x
    
    
    class Foo(metaclass=Meta):
        pass
    
    Foo.attr

    confusing magic methods -- attribute reference

    http://www.sefidian.com/2021/06/06/python-__getattr__-and-__getattribute__-magic-methods/

    __getattr__

    对象中的属性,需要存在,才能访问。

    否则,访问一个不存在的属性,则会导致异常。

    Let’s start with __getattr__. This method will allow you to “catch” references to attributes that don’t exist in your object. Let’s see a simple example to understand how it works:

    In this example, the attribute access fails (with an AttributeError) because the attribute does_not_exist doesn’t exist.

    class Dummy(object):
        passd = Dummy()
    d.does_not_exist  # Fails with AttributeError

    改用此方法捕获不存在方法的访问, 不会抛出异常。

    class Dummy(object):
        def __getattr__(self, attr):
            return attr.upper()d = Dummy()
    d.does_not_exist # 'DOES_NOT_EXIST'
    d.what_about_this_one  # 'WHAT_ABOUT_THIS_ONE'

    但是如果属性存在,则不会激活此函数。

    __getattribute__

    此方法,会对所有的属性的访问,都会被激活。

    __getattribute__ is similar to __getattr__, with the important difference that __getattribute__ will intercept EVERY attribute lookup, doesn’t matter if the attribute exists or not. Let me show you a simple example:

    In that example, the d object already has an attribute value. But when we try to access it, we don’t get the original expected value (“Python”); we’re just getting whatever __getattribute__ returned. It means that we’ve virtually lost the value attribute; it has become “unreachable”.

    __setattr__

    https://python-reference.readthedocs.io/en/latest/docs/dunderattr/setattr.html

    >>> # this example uses __setattr__ to dynamically change attribute value to uppercase
    >>> class Frob:
    ...     def __setattr__(self, name, value):
    ...         self.__dict__[name] = value.upper()
    ...
    >>> f = Frob()
    >>> f.bamf = "bamf"
    >>> f.bamf
    'BAMF'

    __delattr__

    https://python-reference.readthedocs.io/en/latest/docs/dunderattr/delattr.html

    >>> class Frob:
    ...     def __delattr__(self, name):
    ...         print "deleting `{}`".format(str(name))
    ...         del self.__dict__[name]
    ...         print "`{}` deleted".format(str(name))
    ...
    >>> f = Frob()
    >>> f.bamf = 10
    >>> del f.bamf
    deleting `bamf`
    `bamf` deleted

    confusing magic methods -- descriptor

    https://rszalski.github.io/magicmethods/?msclkid=b255353ece8911ec85246d3d9339a225#descriptor

    属性值作为一个对象(descriptor类产生的对象),具有动态计算能力, 依赖的环境为 其定义的类 和 实例。

    适应范围: 依赖计算。

    Descriptors are classes which, when accessed through either getting, setting, or deleting, can also alter other objects. Descriptors aren't meant to stand alone; rather, they're meant to be held by an owner class. Descriptors can be useful when building object-oriented databases or classes that have attributes whose values are dependent on each other. Descriptors are particularly useful when representing attributes in several different units of measurement or representing computed attributes (like distance from the origin in a class to represent a point on a grid).

    To be a descriptor, a class must have at least one of __get__, __set__, and __delete__ implemented. Let's take a look at those magic methods:

    __get__(self, instance, owner)
    Define behavior for when the descriptor's value is retrieved. instance is the instance of the owner object. owner is the owner class itself.
    __set__(self, instance, value)
    Define behavior for when the descriptor's value is changed. instance is the instance of the owner class and value is the value to set the descriptor to.
    __delete__(self, instance)
    Define behavior for when the descriptor's value is deleted. instance is the instance of the owner object.
    class Meter(object):
        '''Descriptor for a meter.'''
    
        def __init__(self, value=0.0):
            self.value = float(value)
        def __get__(self, instance, owner):
            return self.value
        def __set__(self, instance, value):
            self.value = float(value)
    
    class Foot(object):
        '''Descriptor for a foot.'''
    
        def __get__(self, instance, owner):
            return instance.meter * 3.2808
        def __set__(self, instance, value):
            instance.meter = float(value) / 3.2808
    
    class Distance(object):
        '''Class to represent distance holding two descriptors for feet and
        meters.'''
        meter = Meter()
        foot = Foot()

    https://blog.finxter.com/python-__get__-magic-method/?msclkid=529d2a00ce8c11ec909b69d870207cef

    例如下面, 根据宿主对象中的dirname属性,动态计算directory size值。

    import os
    
    class DirectorySize:
    
        def __get__(self, obj, objtype=None):
            return len(os.listdir(obj.dirname))
    
    class Directory:
    
        size = DirectorySize()              # Descriptor instance
    
        def __init__(self, dirname):
            self.dirname = dirname          # Regular instance attribute

    confusing magic methods -- indexer

    __getitem__

    https://www.geeksforgeeks.org/__getitem__-in-python/

    数据类型如果允许使用 [] 去访问元素, 则必然实现了此魔法方法。

    此方法是 容器协议的一部分。

    用于 list索引值, 或者 dict查询。

    __getitem__() is a magic method in Python, which when used in a class, allows its instances to use the [] (indexer) operators. Say x is an instance of this class, then x[i] is roughly equivalent to type(x).__getitem__(x, i).

    The method __getitem__(self, key) defines behavior for when an item is accessed, using the notation self[key]. This is also part of both the mutable and immutable container protocols.

    The __getitem__ magic method is usually used for list indexing, dictionary lookup, or accessing ranges of values. Considering how versatile it is, it’s probably one of Python’s most underutilized magic methods.

    # Code to demonstrate use
    # of __getitem__() in python
    
    
    class Test(object):
        
        # This function prints the type
        # of the object passed as well
        # as the object item
        def __getitem__(self, items):
            print (type(items), items)
    
    # Driver code
    test = Test()
    test[5]
    test[5:65:5]
    test['GeeksforGeeks']
    test[1, 'x', 10.0]
    test['a':'z':2]
    test[object()]

    outputs

    <class 'int'> 5
    <class 'slice'> slice(5, 65, 5)
    <class 'str'> GeeksforGeeks
    <class 'tuple'> (1, 'x', 10.0)
    <class 'slice'> slice('a', 'z', 2)
    <class 'object'> <object object at 0x7f75bcd6d0a0>
    __setitem__ and __getitem__
     
    https://www.geeksforgeeks.org/__getitem__-and-__setitem__-in-python/?msclkid=e23e03cace7611eca9de730da0dd2313
     

    不同于属性的引用方法, 这两个魔法方法适用于索引属性, 例如 数组,词典,列表。

    在这两个方法中,可以提供校验和转换。

    There are getter and setter methods as a part of these magical methods. They are implemented by __getitem__() and __setitem__() methods. But, these methods are used only in indexed attributes like arrays, dictionaries, lists e.t.c. Instead of directly accessing and manipulating class attributes, it provides such methods, so these attributes can be modified only by its own instances and thus implements abstraction.

    Instead of making class attributes as public, these methods make them private, provide validation that only correct values are set to the attributes and the only correct caller has access to these attributes.

    class bank_record:
        
        def __init__(self, name):
            
            self.record = {
                            "name": name,
                            "balance": 100,
                            "transaction":[100]
                            }
    
        def __getitem__(self, key):
            
            return self.record[key]
    
        def __setitem__(self, key, newvalue):
            
            if key =="balance" and newvalue != None and newvalue>= 100:
                self.record[key] += newvalue
                
            elif key =="transaction" and newvalue != None:
                self.record[key].append(newvalue)
        
        def getBalance(self):
            return self.__getitem__("balance")
    
        def updateBalance(self, new_balance):
            
            self.__setitem__("balance", new_balance)
            self.__setitem__("transaction", new_balance)    
        
        def getTransactions(self):
            return self.__getitem__("transaction")
    
        def numTransactions(self):
            return len(self.record["transaction"])
    
    sam = bank_record("Sam")
    print("The balance is : "+str(sam.getBalance()))
    
    sam.updateBalance(200)
    print("The new balance is : "+str(sam.getBalance()))
    print("The no. of transactions are: "+str(sam.numTransactions()))
    
    sam.updateBalance(300)
    print("The new balance is : "+str(sam.getBalance()))
    print("The no. of transactions are: "+str(sam.numTransactions()))
    print("The transaction history is: "+ str(sam.getTransactions()))

     数据类型决定了其可拥有的魔法方法

    https://phoenixnap.com/kb/python-data-types?msclkid=3185a6f7ce7b11eca6bae10924ed6255

    容易混淆的两种概念是  attribute 和 item

    attribute是 object中的一般的概念, 在python中所有的存在都是对象, 每个对象都有 属性, 可以使用 object.attribute 写法来访问。

    item 是abc抽象数据结构中的某些数据结构的实现, 例如 list dict string arrary, 这些数据结构可以看成数据的容器,使用如下写法来访问 object[index]

    如下图, 拥有item性质的数据结构有, list tuple string dict(dictionary)

    但是这里需要说明的是 dict.get 方法, 实质上是对 __getitem__ 的封装,提供了查找不到,返回值的定制能力。

    https://www.tutorialspoint.com/python/dictionary_get.htm?msclkid=18e13d38ce9711ecaecabb37596c6ae5

    dict.get(key, default = None)

    对于查不到返回值定制的需求, 在collection模块中使用 defaultdict来实现。

    Basic Data Types in Python

    A data type is a characteristic that tells the compiler (or interpreter) how a programmer intends to use the data. There are two general categories of data types, differing whether the data is changeable after definition:

    1. Immutable. Data types that are not changeable after assignment.

    2. Mutable. Data types that are changeable after assignment.

    Variables store different types of data. Creating a variable of a particular data type creates an object of a data type class. The Python interpreter automatically assumes a type when creating a variable.

    Python Data Types Overview

    The data type of any object is found using the built-in type() function. The output shows the name of the class for the given object.

    https://docs.python.org/3/library/collections.abc.html?msclkid=6681fc77ce7711eca913c4b402c654b9

    所有的数据结构都继承于ABC

    Collections Abstract Base Classes

    The collections module offers the following ABCs:

    ABC

    Inherits from

    Abstract Methods

    Mixin Methods

    Container 1

     

    __contains__

     

    Hashable 1

     

    __hash__

     

    Iterable 1 2

     

    __iter__

     

    Iterator 1

    Iterable

    __next__

    __iter__

    Reversible 1

    Iterable

    __reversed__

     

    Generator 1

    Iterator

    send, throw

    close, __iter__, __next__

    Sized 1

     

    __len__

     

    Callable 1

     

    __call__

     

    Collection 1

    Sized, Iterable, Container

    __contains__, __iter__, __len__

     

    Sequence

    Reversible, Collection

    __getitem__, __len__

    __contains__, __iter__, __reversed__, index, and count

    MutableSequence

    Sequence

    __getitem__, __setitem__, __delitem__, __len__, insert

    Inherited Sequence methods and append, reverse, extend, pop, remove, and __iadd__

    ByteString

    Sequence

    __getitem__, __len__

    Inherited Sequence methods

    Set

    Collection

    __contains__, __iter__, __len__

    __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__, __sub__, __xor__, and isdisjoint

    MutableSet

    Set

    __contains__, __iter__, __len__, add, discard

    Inherited Set methods and clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__

    Mapping

    Collection

    __getitem__, __iter__, __len__

    __contains__, keys, items, values, get, __eq__, and __ne__

    MutableMapping

    Mapping

    __getitem__, __setitem__, __delitem__, __iter__, __len__

    Inherited Mapping methods and pop, popitem, clear, update, and setdefault

    MappingView

    Sized

     

    __len__

    ItemsView

    MappingView, Set

     

    __contains__, __iter__

    KeysView

    MappingView, Set

     

    __contains__, __iter__

    ValuesView

    MappingView, Collection

     

    __contains__, __iter__

    Awaitable 1

     

    __await__

     

    Coroutine 1

    Awaitable

    send, throw

    close

    AsyncIterable 1

     

    __aiter__

     

    AsyncIterator 1

    AsyncIterable

    __anext__

    __aiter__

    AsyncGenerator 1

    AsyncIterator

    asend, athrow

    aclose, __aiter__, __anext__

  • 相关阅读:
    PHP概率算法---砸金蛋示例
    onethink----网站配置信息调用!
    ajax解决跨域方法(适用于自己写接口解决跨域)
    JavaScript获取地址栏的参数!
    Atitit. null错误的设计 使用Optional来处理null
    Atitit.常用的gc算法
    Atitit.java expression fsm 表达式分词fsm引擎
    Atitit.安全性方案规划设计4gm  v1 q928
    Atitit.安全性方案规划设计4gm  v1 q928
    Atitit.java expression fsm 表达式分词fsm引擎
  • 原文地址:https://www.cnblogs.com/lightsong/p/16245555.html
Copyright © 2020-2023  润新知