程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Divine skill! Perform four kinds of black box operations during Python class initialization!

編輯:Python

Python In the class , All with double underline __ How to wrap it up , It's called magic method , Magic methods can be executed automatically after some events of a class or object are issued , Let classes have magical magic , For example, common construction methods __new__、 Initialization method __init__、 destructor __del__, Let's talk today __new__ The magic effect of , The main points are as follows :

  • __new__ and __init__ The difference between

  • application 1: Change the built-in immutable type

  • application 2: Implement a single example

  • application 3: Client cache

  • application 4: Different files have different decryption methods

  • application 5:Metaclasses

__new__ and __init__ The difference between

1、 Call timing is different :new Is the way to actually create an instance ,init For instance initialization ,new Precede init function .

2、 Different return values ,new Returns an instance of a class , and init Don't return any information .

3、new yes class Methods , and init It's the method of the object .

Sample code :

class A:
    def __new__(cls, *args, **kwargs):
        print("new", cls, args, kwargs)
        return super().__new__(cls)
    def __init__(self, *args, **kwargs):
        print("init", self, args, kwargs)
def how_object_construction_works():
    x = A(1, 2, 3, x=4)
    print(x)    
    print("===================")
    x = A.__new__(A, 1, 2, 3, x=4)
    if isinstance(x, A):
        type(x).__init__(x, 1, 2, 3, x=4)
    print(x)
if __name__ == "__main__":
    how_object_construction_works()

The above code defines a class A, Calling A(1, 2, 3, x=4) We'll do it first new, Re execution init, Equivalent to :

x = A.__new__(A, 1, 2, 3, x=4)
if isinstance(x, A):
    type(x).__init__(x, 1, 2, 3, x=4)

The code runs as follows :

new <class '__main__.A'> (1, 2, 3) {'x': 4}
init <__main__.A object at 0x7fccaec97610> (1, 2, 3) {'x': 4}
<__main__.A object at 0x7fccaec97610>
===================
new <class '__main__.A'> (1, 2, 3) {'x': 4}
init <__main__.A object at 0x7fccaec97310> (1, 2, 3) {'x': 4}
<__main__.A object at 0x7fccaec97310>

new The main function of creating custom classes is to let programmers create custom behaviors , Here are Python Construction method of  __new__  Common scenarios :

application 1: Change the built-in immutable type

We know , Tuples are immutable types , But we inherit tuple , Then you can go to new in , Modify the element of its tuple , because new Before returning , Tuples are not tuples , This is in init Functions cannot be implemented . for instance , Implement an uppercase tuple , The code is as follows :

class UppercaseTuple(tuple):
    def __new__(cls, iterable):
        upper_iterable = (s.upper() for s in iterable)
        return super().__new__(cls, upper_iterable)
    #  The following code will report an error , It cannot be modified during initialization
    # def __init__(self, iterable):
    #     print(f'init {iterable}')
    #     for i, arg in enumerate(iterable):
    #         self[i] = arg.upper()
if __name__ == '__main__':
    print("UPPERCASE TUPLE EXAMPLE")
    print(UppercaseTuple(["hello", "world"]))
# UPPERCASE TUPLE EXAMPLE
# ('HELLO', 'WORLD')

application 2: Implement a single example

class Singleton:
    _instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance
if __name__ == "__main__":
    print("SINGLETON EXAMPLE")
    x = Singleton()
    y = Singleton()
    print(f"{x is y=}")
# SINGLETON EXAMPLE
# x is y=True

application 3: Client cache

When the creation cost of the client is relatively high , Such as reading files or databases , The following methods can be used , The same client belongs to the same instance , Save the cost of creating objects , This is essentially a multi instance pattern .

class Client:
    _loaded = {}
    _db_file = "file.db"
    def __new__(cls, client_id):
        if (client := cls._loaded.get(client_id)) is not None:
            print(f"returning existing client {client_id} from cache")
            return client
        client = super().__new__(cls)
        cls._loaded[client_id] = client
        client._init_from_file(client_id, cls._db_file)
        return client
    def _init_from_file(self, client_id, file):
        # lookup client in file and read properties
        print(f"reading client {client_id} data from file, db, etc.")
        name = ...
        email = ...
        self.name = name
        self.email = email
        self.id = client_id
if __name__ == '__main__':
    print("CLIENT CACHE EXAMPLE")
    x = Client(0)
    y = Client(0)
    print(f"{x is y=}")
    z = Client(1)
# CLIENT CACHE EXAMPLE
# reading client 0 data from file, db, etc.
# returning existing client 0 from cache
# x is y=True
# reading client 1 data from file, db, etc.

application 4: Different files have different decryption methods

First create three files in the directory where the script is located :plaintext_hello.txt、rot13_hello.txt、otp_hello.txt, The program will choose different decryption algorithms according to different files

import codecs
import itertools
class EncryptedFile:
    _registry = {}  # 'rot13' -> ROT13Text
    def __init_subclass__(cls, prefix, **kwargs):
        super().__init_subclass__(**kwargs)
        cls._registry[prefix] = cls
    def __new__(cls, path: str, key=None):
        prefix, sep, suffix = path.partition(":///")
        if sep:
            file = suffix
        else:
            file = prefix
            prefix = "file"
        subclass = cls._registry[prefix]
        obj = object.__new__(subclass)
        obj.file = file
        obj.key = key
        return obj
    def read(self) -> str:
        raise NotImplementedError
class Plaintext(EncryptedFile, prefix="file"):
    def read(self):
        with open(self.file, "r") as f:
            return f.read()
class ROT13Text(EncryptedFile, prefix="rot13"):
    def read(self):
        with open(self.file, "r") as f:
            text = f.read()
        return codecs.decode(text, "rot_13")
class OneTimePadXorText(EncryptedFile, prefix="otp"):
    def __init__(self, path, key):
        if isinstance(self.key, str):
            self.key = self.key.encode()
    def xor_bytes_with_key(self, b: bytes) -> bytes:
        return bytes(b1 ^ b2 for b1, b2 in zip(b, itertools.cycle(self.key)))
    def read(self):
        with open(self.file, "rb") as f:
            btext = f.read()
        text = self.xor_bytes_with_key(btext).decode()
        return text
if __name__ == "__main__":
    print("ENCRYPTED FILE EXAMPLE")
    print(EncryptedFile("plaintext_hello.txt").read())
    print(EncryptedFile("rot13:///rot13_hello.txt").read())
    print(EncryptedFile("otp:///otp_hello.txt", key="1234").read())
# ENCRYPTED FILE EXAMPLE
# plaintext_hello.txt
# ebg13_uryyb.gkg
# ^FCkYW_X^GL

END

 Recommended reading :
introduction :  The most complete zero Foundation Python The problem of   |  Zero Basics 8 Months Python  |  Actual project  | learn Python That's the shortcut
dried food : A short comment on crawling Douban , The movie 《 The rest of us 》 | 38 year NBA Best player analysis  |    From people's expectation to public praise ! Tang Dynasty detective 3 disappointing   |  Laugh at the story of the new Yitian dragon slaying  |  Riddle answer King  | use Python Make a massive sketch of my little sister  | Mission impossible is so hot , I use machine learning to make a mini recommendation system movie
Interest : Pinball game   |  squared paper for practicing calligraphy   |  Beautiful flowers  |  Two hundred lines Python《 Cool run every day 》 game !
AI:  A robot that can write poetry  |  Color the picture  |  Forecast revenue  |  Mission impossible is so hot , I use machine learning to make a mini recommendation system movie
Gadget : Pdf turn Word, Easily handle forms and watermarks ! |  One touch html Save the page as pdf!|   bye PDF Withdrawal charges ! |  use 90 Lines of code create the strongest PDF converter ,word、PPT、excel、markdown、html One click conversion  |  Make a nail low-cost ticket reminder ! |60 Line of code to do a voice wallpaper switcher, look at my little sister every day !|

Annual hot money copy

  • 1). Oh my god !Pdf turn Word use Python Easy to handle !

  • 2). learn Python It's delicious ! I use 100 Line of code to make a website , Help people PS Travel pictures , Earn a chicken leg to eat

  • 3). Premiere billions , Hot all over the net , I analyzed 《 My sister 》, Discovered the secrets  

  • 4).80 Line code ! use Python Make a dorai A Dream separation  

  • 5). What you have to master 20 individual python Code , short , Useful  

  • 6).30 individual Python Strange sexual skills Collection  

  • 7). I summed up 80 page 《 Rookie Science Python Select dry goods .pdf》, Is dry  

  • 8). bye Python! I have to learn Go 了 !2500 Word depth analysis !

  • 9). Found a licking dog welfare ! This Python Reptile artifact is great , Automatically download sister pictures

Click to read the original , see 200 individual Python Case study !


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved