Movatterモバイル変換


[0]ホーム

URL:


— FREE Email Series —

🐍 Python Tricks 💌

Python Tricks Dictionary Merge

🔒 No spam. Unsubscribe any time.

Browse TopicsGuided Learning Paths
Basics Intermediate Advanced
apibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnumpyprojectspythontestingtoolsweb-devweb-scraping

Table of Contents

Python's .__call__() Method: Creating Callable Instances

Python's .__call__() Method: Creating Callable Instances

byLeodanis Pozo Ramosintermediatepython

Table of Contents

Remove ads

In Python, acallable is any object that you can call using a pair of parentheses and, optionally, a series of arguments. Functions, classes, and methods are all common examples of callables in Python. Besides these, you can also create custom classes that producecallable instances. To do this, you can add the.__call__() special method to your class.

Instances of a class with a.__call__() method behave like functions, providing a flexible and handy way to add functionality to your objects. Understanding how to create and use callable instances is a valuable skill for you as a Python developer.

In this tutorial, you’ll:

  • Understand the concept ofcallable objects in Python
  • Createcallable instances by providing your classes with a.__call__() method
  • Understand thedifference between.__init__() and.__call__()
  • Code several examples of using callable instances to solvereal-world problems

To get the most out of this tutorial, you should be comfortable with the basics ofobject-oriented programming in Python, including how to define and useclasses and methods. Some familiarity with Pythondecorators and thestrategy design pattern will also help. You should also understand the concept ofstate.

Free Bonus:Click here to download your sample code so that you can create callable instances with Python’s.__call__() method.

Understanding Callable Objects in Python

Acallable in Python is any object that you can call using a pair of parentheses and a series of arguments if required. You’ll find different examples of callables in your daily interaction with Python. Some of them include:

All these different callables have something in common. They all implement the.__call__()special method. To confirm this fact, you can use the built-indir() function, which takes an object as an argument andreturns the object’s list of attributes and methods:

Python
>>>dir(abs)[    '__call__',    '__class__',    ...]>>>dir(all)[    '__call__',    '__class__',    ...]>>>defgreet():...print("Hello, World!")...>>>dir(greet)[    '__annotations__',    '__builtins__',    '__call__',    ...]

In the first two examples, you calldir() with the built-inabs() andall() functions as arguments. In both cases, you can see that the.__call__() method is present in the output.

In the final example, you define a custom function thatprints a message to the screen. This function also has.__call__(). Note how you can use this method to call the function:

Python
>>>greet.__call__()Hello, World!

Note that using.__call__() as you did in this example produces the same effect as calling the function directly withgreet().

Note: Even though you can call special methods like.__call__() directly, doing so isn’t a recommended or best practice. Instead, call the functions as usual.

Now, how does all this work internally? When you run something likecallable_object(*args, **kwargs), Python internally translates the operation intocallable_object.__call__(*args, **kwargs). The arguments to the regular function are the same as those used in.__call__(). In other words, whenever you call a callable object, Python automatically runs its.__call__() method behind the scenes using the arguments you’ve passed into the callable.

Now take a look at the following custom class:

Python
>>>classSampleClass:...defmethod(self):...print("You called method()!")...>>>type(SampleClass)<class 'type'>>>>dir(type)[    '__abstractmethods__',    '__annotations__',    '__base__',    '__bases__',    '__basicsize__',    '__call__',    ...]>>>sample_instance=SampleClass()>>>dir(sample_instance.method)[    '__call__',    '__class__',    ...]

In Python, everything is an object. Classes likeSampleClass are objects oftype, which you can confirm by callingtype() with the class object as an argument or by accessing the.__class__ attribute.

Theclass constructor ofSampleClass falls back to usingtype.__call__(). That’s why you can callSampleClass() to get a new instance. So, class constructors are callable objects that return new instances of the underlying class.

In the example above, you can observe that method objects, likesample_instance.method, also have a.__call__() special method that turns them into callable objects. The main takeaway here is that to be callable, an object needs to have a.__call__() method.

If you inspect a closure, generator function, or asynchronous function, then you’ll get similar results. You’ll always find a.__call__() method in callable objects.

Checking Whether an Object Is Callable

If you ever need to check whether a Python object is callable, then you can use the built-incallable() function like in the following examples:

Python
>>>callable(abs)True>>>callable(all)True>>>callable(greet)True>>>callable(SampleClass)True>>>callable(sample_instance)False

Thecallable() function takes an object as an argument and returnsTrue if the object is callable. Otherwise, it returnsFalse.

Note: Becausedir() checks if a given object has a.__call__() method, youcould use it to check if that object is callable. Even thoughdir() can be useful when you’re experimenting with code and examples, isn’t particularly helpful when you need to quickly check whether an object is callable. Thecallable() function, in contrast, is apredicate function that you can directly use in aBoolean context.

In the above examples, all the tested objects are callable except forsample_instance. That’s foreseeable becauseSampleClass doesn’t implement a.__call__() method for its instances. Yes, you guessed it! You can make the instances of your custom classes callable by writing a.__call__() method. In the following section, you’ll learn the basics of turning the instances of your classes into callable objects.

But first, it’s important to note that sometimescallable() may produce false positives:

Python
>>>classNonCallable:...def__call__(self):...raiseTypeError("not really callable")...>>>instance=NonCallable()>>>callable(instance)True>>>instance()Traceback (most recent call last):...TypeError:not really callable

In this example,callable() returnsTrue. However, instances of this custom class aren’t callable, and you get an error if you try to call them. So,callable() only guarantees that the target instance comes from a class that implements a.__call__() method.

Creating Callable Instances With.__call__() in Python

If you want the instances of a given class to be callable, then you need to implement the.__call__() special method in the underlying class. This method enables you to call the instances of your class as you’d call regular Python functions.

Unlike other special methods,.__call__() doesn’t have special requirements for what arguments it must accept. It works like any other instance method in the sense that it takesself as its first argument and can take as many extra arguments as you need.

Here’s an example of how instances of a class with a.__call__() method work:

Python
# counter.pyclassCounter:def__init__(self):self.count=0defincrement(self):self.count+=1def__call__(self):self.increment()

In thisCounter class, you have a.countinstance attribute to keep track of the current count. Then you have an.increment() method that adds1 to the count every time you call it. Finally, you add a.__call__() method. In this example,.__call__() falls back to calling.increment(), providing a shortcut for running the increment operation.

Take a look at how the class works in practice:

Python
>>>fromcounterimportCounter>>>counter=Counter()>>>counter.increment()>>>counter.count1>>>counter()>>>counter.count2>>>counter()>>>counter.count3

After creating an instance ofCounter, you call.increment(). This call increments the.count attribute by1, as you can confirm by accessing the attribute. In the rest of the examples, you take advantage of the fact that your class has a.__call__() method and call the instance directly to increment the count.

In this example,.__call__() provides a quick shortcut for running the count increment operation. This feature gives your class a convenient and user-friendly interface.

The.__call__() method in the above example doesn’t take any arguments. The method doesn’t return an explicit value either. However, there are no restrictions on how to write the.__call__() method in your custom classes. So, you can make them take arguments, return values, and even causeside effects like in yourCounter class example.

For a second example, consider the following class, which allows you to create callable objects to compute different powers:

Python
# power.pyclassPowerFactory:def__init__(self,exponent=2):self.exponent=exponentdef__call__(self,base):returnbase**self.exponent

In this example, yourPowerFactory class takesexponent as an argument, which you’ll use later to run different power operations. The.__call__() method takes abase argument and calculates its power using the previously provided exponent. Finally, the method returns the computed result.

Here’s your class in action:

Python
>>>frompowerimportPowerFactory>>>square_of=PowerFactory(2)>>>square_of(3)9>>>square_of(6)36>>>cube_of=PowerFactory(3)>>>cube_of(3)27>>>cube_of(6)216

Here, you usePowerFactory to create two different callable instances. The first instance raises numbers to the power of2, while the second instance raises numbers to the power of3.

In this example, you need to passbase as an argument when callingsquare_of() orcube_of() because those calls fall back to calling.__call__(), which takes abase argument. Finally, note how you get the power back from every call. That’s because.__call__() returns the result of calculating the desired power.

Defining a.__call__() method in custom classes allows you to use the instances of those classes as regular Python functions. This feature can come in handy in several situations, as you’ll learn in the sectionPutting Python’s.__call__() Into Action.

Before jumping into common use cases of callable instances, you’ll explore the differences between the.__init__() and.__call__() methods. These two methods and their corresponding roles in Python classes can be confusing for people who are beginning to work with Python.

Understanding the Difference:.__init__() vs.__call__()

Differentiating the roles of.__init__() and.__call__() in a Python class can be a confusing task for developers who are starting to study the language or itsobject-oriented features. However, these two methods are pretty different, and each one has specific goals.

The.__init__() method is theinstance initializer. Python calls this method automatically whenever you create an instance of a class by calling the class constructor. The arguments to.__init__() will be the same as the arguments to the class constructor, and they’ll typically provide initial values for instance attributes.

Meanwhile, the.__call__() methodturns instances into callable objects. As you already learned, Python automatically calls this method whenever you call a concrete instance of a given class.

To illustrate the differences between both methods, consider the following example class:

Python
>>>classDemo:...def__init__(self,attr):...print(f"Initialize an instance of{self.__class__.__name__}")...self.attr=attr...print(f"{self.attr= }")......def__call__(self,arg):...print(f"Call an instance of{self.__class__.__name__} with{arg}")...

ThisDemo class implements both.__init__() and.__call__(). In.__init__(), you print a message and initialize the.attr attribute. In.__call__(), you only print a message so that you learn when the method gets called with a given argument.

Here’s how this class works:

Python
>>>demo=Demo("Some initial value")Initialize an instance of Demoself.attr = 'Some initial value'>>>demo("Hello!")Call an instance of Demo with Hello!

As you can see, each method has a different role in your class. The.__init__() method gets called when you create instances of the class. Its main goal is to initialize instance attributes with sensible initial values.

You’ll find.__init__() in all Python classes. Some classes will have an explicit implementation, and others willinherit the method from a parent class. In many cases,object is the class that provides this method:

Python
>>>dir(object)[    ...    '__gt__',    '__hash__',    '__init__',    ...]

Remember thatobject is the ultimate parent class of all Python classes. So, even if you don’t define an explicit.__init__() method in one of your custom classes, that class will still inherit the default implementation fromobject.

In contrast, the.__call__() method runs when you call a concrete instance of its containing class, such asdemo in this example. The goal of.__call__() is to turn your instances into callable objects. In other words, its purpose is to create objects that you can call as you would call a regular function. Most Python classes don’t implement this method. Your custom classes will have it only if you need to use your instances as functions.

Great! After clarifying the differences between.__call__() and.__init__(), you’re ready to continue learning about.__call__() by discovering how you can take advantage of this method in your Python code.

Putting Python’s.__call__() Into Action

Writing classes that produce callable instances can be pretty useful in a few situations. For example, you can take advantage of callable instances when you need to:

  • Retain state between calls
  • Cache values that result fromprevious computations
  • Implement straightforward and convenientAPIs

Even though you can use functions or classes with regular methods to solve all these problems, using callable instances may be a good option in some situations. This is especially true when you already have an existing class and face the need for function-like behavior.

In the following sections, you’ll write practical examples that illustrate each of these use cases of callable instances in Python.

Writing Stateful Callables

Sometimes, you may want to write callable objects that retainstate between calls, which are commonly known asstateful callables. For example, say that you want to write a callable that takes consecutive numeric values from a data stream and computes their cumulative average. Between calls, the callable must keep track of previously passed values.

To solve this problem, you can use aclosure that looks something like this:

Python
>>>defcumulative_average():...data=[]...defaverage(new_value):...data.append(new_value)...returnsum(data)/len(data)...returnaverage...>>>stream_average=cumulative_average()>>>stream_average(12)12.0>>>stream_average(13)12.5>>>stream_average(11)12.0>>>stream_average(10)11.5

Incumulative_average(), you use a local variable calleddata to hold the data between calls. Then you define an inner function calledaverage(). This function takes a new value in each call and appends it todata. Then the function computes and returns the average of the currently stored data.

Finally,cumulative_average() returns the inner function. In practice, it returns a closure, which is a special object that packs together theaverage() function and itsnon-local scope. In this example, that closure includes thedata variable.

Once you’ve finished writingcumulative_average(), then you can create custom closures likestream_average. This object is callable, so you can use it as a function to compute the cumulative average of a data stream, as you did in the final examples above.

Even though closures allow you to retain state between calls, these tools may be hard to understand and process. In this sense, writing a class with a.__call__() method can facilitate the task and make your code more readable and explicit.

Note: To dive deeper into closures and scopes in Python, check outExploring Scopes and Closures in Python.

Here’s how you can solve the above problem using a class with a.__call__() method:

Python
# cumulative_average.pyclassCumulativeAverager:def__init__(self):self.data=[]def__call__(self,new_value):self.data.append(new_value)returnsum(self.data)/len(self.data)

In this example, your class has an instance attribute called.data to hold the data. The.__call__() method takes a new value in each call, appends the value to.data, and finally computes and returns the average.

In this case, your code is quite readable. The.data attribute retains the state between calls, while the.__call__() method computes the cumulative average. Here’s how this class works in practice:

Python
>>>fromcumulative_averageimportCumulativeAverager>>>stream_average=CumulativeAverager()>>>stream_average(12)12.0>>>stream_average(13)12.5>>>stream_average(11)12.0>>>stream_average(10)11.5>>>stream_average.data[12, 13, 11, 10]

The instances ofCumulativeAverager are callables that retain the previously entered values and compute the cumulative average in each call. This approach makes your code easier to reason about. To write this class, you don’t have to know about the intricacies of how closures work in Python.

Another interesting advantage is that now you have direct access to the current data through the.data attribute.

Caching Computed Values

Another common use case of callable instances is when you need a stateful callable thatcaches computed data between calls. This will be handy when you need to optimize some algorithms.

For example, say that you want to compute the factorial of a given number. Because you plan to run this computation multiple times, you need to make it efficient. A way to do this is to cache the already-computed values so that you don’t have to recompute them all the time.

Here’s a class that achieves this result using.__call__() and caching:

Python
# factorial.pyclassFactorial:def__init__(self):self.cache={0:1,1:1}def__call__(self,number):ifnumbernotinself.cache:self.cache[number]=number*self(number-1)returnself.cache[number]

In this class, you use adictionary to cache already-computed factorial values. The dictionary keys hold already-passed numbers, and the dictionary values hold already-calculated factorials.

The.__call__() method checks if the current input number is already in the.cache dictionary. If that’s the case, then the method returns the corresponding value without running the computation again. This behavior optimizes your algorithm, making it faster.

If the current input number isn’t in the.cache dictionary, then the method computes the factorial recursively, caches the result, and returns the final value to the caller.

Here’s how this class works:

Python
>>>fromfactorialimportFactorial>>>factorial_of=Factorial()>>>factorial_of(4)24>>>factorial_of(5)120>>>factorial_of(6)720>>>factorial_of.cache{0: 1, 1: 1, 2: 2, 3: 6, 4: 24, 5: 120, 6: 720}

Each call to the instance ofFactorial checks the cache for already-computed values. The instance only computes factorials for those numbers that haven’t been passed yet. Note how all the input values and their corresponding factorials end up stored in the.cache dictionary.

Creating Clear and Convenient APIs

Writing classes that produce callable instances also allows you to design convenient and user-friendlyapplication programming interfaces (APIs) for your libraries,packages, and modules.

For example, say you’re writing a new and cool library for creatingGUI applications. Your library will have aMainWindow class that provides all the functionalities to create the main window of your GUI apps.

The class will have several methods, including a.show() method to draw the window on the screen. In this case, you can provide a.__call__() method like the following:

Python
classMainWindow:defshow(self):print("Showing the app's main window...")def__call__(self):self.show()# ...

In this example, the.__call__() method falls back to calling the.show() method. This implementation enables you to show your main window by calling either.show() or the window instance itself:

Python
window=MainWindow()window()# Or window.show()

In this example,.__call__() provides a handy shortcut to display the app’s window on your screen. This can improve your user’s experience. So, this trick is a great way to create user-friendly and intuitive interfaces for your Python projects.

Another use case where.__call__() can help you improve your APIs is when you have a class whose primary purpose is to provide a single action or behavior. For example, say you want aLogger class that takes care of logging messages to a file:

Python
# logger.pyclassLogger:def__init__(self,filename):self.filename=filenamedef__call__(self,message):withopen(self.filename,mode="a",encoding="utf-8")aslog_file:log_file.write(message+"\n")

In this example, the main purpose ofLogger is to write messages to a log file that you should provide. By implementing the.__call__() method, you provide a shortcut for accessing this functionality by calling the object like a function.

Exploring Advanced Use Cases of.__call__()

So far, you’ve learned a lot about creating callable instances using the.__call__() method in your classes. This method also has some advanced use cases in Python. One of these use cases is when you want to createclass-based decorators. In this situation, the.__call__() method is the only way to go because it enables callable instances.

Another interesting use case of.__call__() is when you need to implement thestrategy design pattern in Python. In this case, you can take advantage of.__call__() to create classes that provide implementations for your different strategies.

In the following sections, you’ll learn how to use.__call__() to create class-based decorators and also to implement the strategy pattern in Python.

Writing Class-Based Decorators

Python’sdecorators are callables that take another callable as an argument and extend its behavior without explicitly modifying its code. Decorators provide an excellent tool for adding new functionality to existing callables.

It’s pretty common to find and writefunction-based decorators. However, you can also writeclass-based decorators by taking advantage of the.__call__() special method.

To illustrate how you can do this, say that you want to create a decorator that measures the execution time of your custom functions. The code below shows how you can write this decorator as a class:

Python
# timing.pyimporttimeclassExecutionTimer:def__init__(self,func):self.func=funcdef__call__(self,*args,**kwargs):start=time.perf_counter()result=self.func(*args,**kwargs)end=time.perf_counter()print(f"{self.func.__name__}() took{(end-start)*1000:.4f} ms")returnresult

TheExecutionTimer class takes a function object as an argument at instantiation time. The.__call__() method operates on that function object. In this example,.__call__() uses the*args and**kwargs generic arguments to handle any arguments that the input function requires.

Next, you usetime.perf_counter() to get the time before and after the input function executes. Then you print a message with the function’s name and the execution time in milliseconds. The final step is to return the result of calling the input function.

Note: For a deep dive into best practices for timing code in Python, check outPython Timer Functions: Three Ways to Monitor Your Code.

With this class in place, you can start measuring the execution time of your Python functions right away:

Python
>>>fromtimingimportExecutionTimer>>>@ExecutionTimer...defsquare_numbers(numbers):...return[number**2fornumberinnumbers]...>>>square_numbers(list(range(100)))square_numbers() took 0.0069 ms[    0,    1,    4,    9,    16,    25,    ...]

In this code snippet, you have a function that takes a list of numbers and returns a list of square values. You want to measure the execution time of this function, so you use your@ExecutionTimer decorator to that end.

Once the function is decorated, whenever you run it, you get a message with the function name and the execution time in milliseconds. Then you get the function’s return value.

Now say that you want to add arepetitions argument to your decorator. This argument will allow you to run the input function several times and compute the average execution time:

Python
# timing.pyimporttimeclassExecutionTimer:def__init__(self,repetitions=1):self.repetitions=repetitionsdef__call__(self,func):deftimer(*args,**kwargs):result=Nonetotal_time=0print(f"Running{func.__name__}(){self.repetitions} times")for_inrange(self.repetitions):start=time.perf_counter()result=func(*args,**kwargs)end=time.perf_counter()total_time+=end-startaverage_time=total_time/self.repetitionsprint(f"{func.__name__}() takes "f"{average_time*1000:.4f} ms on average")returnresultreturntimer

This updated version ofExecutionTimer is quite different from your original implementation. The class initializer takesrepetitions an argument that you need to provide as part of the decorator call.

In.__call__(), you take the input function as an argument. Then you create an inner function to process the input function’s execution. Inside this inner function, you use afor loop to run the input function multiple times and compute the total execution time.

Next, you calculate the average execution time and print an informative message as usual. Finally, you return the input function’s result. Note that.__call__() returns the function object represented bytimer.

With these changes in place, go ahead and tryExecutionTimer again. Note that to access this new version ofExecutionTimer, you need toreload thetiming.py file or restart your currentinteractive session first:

Python
>>>fromtimingimportExecutionTimer>>>@ExecutionTimer(repetitions=100)...defsquare_numbers(numbers):...return[number**2fornumberinnumbers]...>>>square_numbers(list(range(100)))Running square_numbers() 100 timessquare_numbers() takes 0.0073 ms on average[    0,    1,    4,    9,    16,    25,    ...]

Your decorator now allows you to run the target function a specific number of times and calculate the average execution time. That’s great!

Implementing the Strategy Design Pattern

Thestrategy design pattern allows you to define a family of similar algorithms and make them interchangeable at runtime. In other words, the pattern implements different solutions to a given type of problem, with each solution bundled in a specific object. Then, you can choose the appropriate solution dynamically.

Note: The strategy design pattern is also pretty useful in languages where functions aren’tfirst-class citizens. For example, inC++ orJava, using this pattern allows you to pass functions as arguments to other functions.

As an example of how to use.__call__() to implement the strategy pattern, say that you need toserialize some data intoJSON orYAML, depending on certain conditions. In this case, you can use the strategy pattern. You’ll have a class to serialize data into JSON and another class to serialize data into YAML.

In the example below, you’ll code a possible solution to your problem. Note that for the example to work, you first need toinstallpyyaml usingpip because the Python standard library doesn’t offer appropriate tools for processing YAML data. It’s amissing battery.

Note: To installpyyaml, you should first create a Pythonvirtual environment if you haven’t yet. That way, you’ll avoid cluttering your system Python installation with packages that you won’t use on a daily basis.

Here’s your code:

Python
# serializing.pyimportjsonimportyamlclassJsonSerializer:def__call__(self,data):returnjson.dumps(data,indent=4)classYamlSerializer:def__call__(self,data):returnyaml.dump(data)classDataSerializer:def__init__(self,serializing_strategy):self.serializing_strategy=serializing_strategydefserialize(self,data):returnself.serializing_strategy(data)

In this example, you have theJsonSerializer andYamlSerializer classes, which represent your serializing strategies. Their.__call__() methods use appropriate tools to serialize the input data into JSON and YAML, respectively.

Then you have theDataSerializer class, which provides the higher-level class. You’ll use this class to serialize your data. First, you need to provide an appropriate callable instance of a concrete serializer class:

Python
>>>fromserializingimportDataSerializer,JsonSerializer,YamlSerializer>>>data={..."name":"Jane Doe",..."age":30,..."city":"Salt Lake City",..."job":"Python Developer",...}>>>serializer=DataSerializer(JsonSerializer())>>>print(f"JSON:\n{serializer.serialize(data)}")JSON:{    "name": "Jane Doe",    "age": 30,    "city": "Salt Lake City",    "job": "Python Developer"}>>># Switch strategy>>>serializer.serializing_strategy=YamlSerializer()>>>print(f"YAML:\n{serializer.serialize(data)}")YAML:age: 30city: Salt Lake Cityjob: Python Developername: Jane Doe

In this code snippet, you have a dictionary containing some sample data. To process this data, you create an instance ofDataSerializer usingJsonSerializer as an argument. After this step, your instance can convert your dictionary into JSON.

In the final example, you change the serializing strategy and use your data serializer to convert the data into YAML code. Do you have ideas for other useful data serializers?

Conclusion

You’ve learned a lot aboutcallable instances in Python, especially how to define them using the.__call__() special method in your custom classes. Now you know how to create classes that produce objects that you can call just like regular functions. This allows you to add flexibility and functionality to your object-oriented programs.

In this tutorial, you’ve learned how to:

  • Comprehendcallables in Python
  • Writecallable instances by using the.__call__() method
  • Grasp thedifference between.__init__() and.__call__()
  • Implement various examples of using callable instances to tacklepractical issues

With this knowledge, you can design and implement callable instances in your Python code. This will allow you to solve various common problems, such as retaining state between calls, caching data, writing class-based decorators, and more.

Free Bonus:Click here to download your sample code so that you can create callable instances with Python’s.__call__() method.

🐍 Python Tricks 💌

Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

AboutLeodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

» More about Leodanis

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

MasterReal-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

MasterReal-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.


Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics:intermediatepython

Related Tutorials:

Keep reading Real Python by creating a free account or signing in:

Already have an account?Sign-In

Almost there! Complete this form and click the button below to gain instant access:

Python's .__call__() Method: Creating Callable Instances

Python's .__call__() Method: Creating Callable Instances (Sample Code)

🔒 No spam. We take your privacy seriously.


[8]ページ先頭

©2009-2025 Movatter.jp