Python __call__ special method practical example

后端 未结 14 1510
感动是毒
感动是毒 2020-11-28 00:28

I know that __call__ method in a class is triggered when the instance of a class is called. However, I have no idea when I can use this special method, because

相关标签:
14条回答
  • 2020-11-28 01:22

    I find a good place to use callable objects, those that define __call__(), is when using the functional programming capabilities in Python, such as map(), filter(), reduce().

    The best time to use a callable object over a plain function or a lambda function is when the logic is complex and needs to retain some state or uses other info that in not passed to the __call__() function.

    Here's some code that filters file names based upon their filename extension using a callable object and filter().

    Callable:

    import os
    
    class FileAcceptor(object):
        def __init__(self, accepted_extensions):
            self.accepted_extensions = accepted_extensions
    
        def __call__(self, filename):
            base, ext = os.path.splitext(filename)
            return ext in self.accepted_extensions
    
    class ImageFileAcceptor(FileAcceptor):
        def __init__(self):
            image_extensions = ('.jpg', '.jpeg', '.gif', '.bmp')
            super(ImageFileAcceptor, self).__init__(image_extensions)
    

    Usage:

    filenames = [
        'me.jpg',
        'me.txt',
        'friend1.jpg',
        'friend2.bmp',
        'you.jpeg',
        'you.xml']
    
    acceptor = ImageFileAcceptor()
    image_filenames = filter(acceptor, filenames)
    print image_filenames
    

    Output:

    ['me.jpg', 'friend1.jpg', 'friend2.bmp', 'you.jpeg']
    
    0 讨论(0)
  • 2020-11-28 01:23

    I find it useful because it allows me to create APIs that are easy to use (you have some callable object that requires some specific arguments), and are easy to implement because you can use Object Oriented practices.

    The following is code I wrote yesterday that makes a version of the hashlib.foo methods that hash entire files rather than strings:

    # filehash.py
    import hashlib
    
    
    class Hasher(object):
        """
        A wrapper around the hashlib hash algorithms that allows an entire file to
        be hashed in a chunked manner.
        """
        def __init__(self, algorithm):
            self.algorithm = algorithm
    
        def __call__(self, file):
            hash = self.algorithm()
            with open(file, 'rb') as f:
                for chunk in iter(lambda: f.read(4096), ''):
                    hash.update(chunk)
            return hash.hexdigest()
    
    
    md5    = Hasher(hashlib.md5)
    sha1   = Hasher(hashlib.sha1)
    sha224 = Hasher(hashlib.sha224)
    sha256 = Hasher(hashlib.sha256)
    sha384 = Hasher(hashlib.sha384)
    sha512 = Hasher(hashlib.sha512)
    

    This implementation allows me to use the functions in a similar fashion to the hashlib.foo functions:

    from filehash import sha1
    print sha1('somefile.txt')
    

    Of course I could have implemented it a different way, but in this case it seemed like a simple approach.

    0 讨论(0)
提交回复
热议问题