
[ad_1]
Level up your Python skills
The core of any application is data. If you are building a social networking website, users and their friendships are data. If you’re making a game, graphics and user operations are data. If you are building an online shopping store, product and customer information are data. These are some examples from our daily life.
Data are not very meaningful if they are presented in their raw form. You must define specific operations to process the data before it is presented. These specific operations typically take the form of a function – a block of code that accepts input, applies operations, and produces output. I would say that functions are the underlying driving force for any programming project.
In this article, I want to summarize three things that you as a Python programmer can consider when writing functions.
Please note that I will not cover some general best practices in defining functions, such as sensible names, dedicated purposes (not mixed concerns), and proper docstrings. Instead, my angle is more from a technical standpoint.
Without further ado, let’s get started.
It is ideal that a function does not require any input. When users call this function, they don’t have to worry about setting any arguments. However, in most cases, functions require specific inputs such that they can perform the intended operations.
When a function takes multiple arguments, one technique to simplify the function call is to set default arguments. This feature is widely used in the standard Python library. For example, the following is the calling signature of the built-in: sorted
Celebration.
sorted(iterable, /, *, key=None, reverse=False)
In this ceremony, key
And reverse
Parameters have their own default values — the key
The argument specifies how the sorting is performed (None
means using the default lexicographic or numerical order) and reverse
The argument specifies whether the order is descending. In most cases, when we call this function, we don’t need to worry about setting key
And reverse
, However, when we want to define a custom sorting operation, we can set key
Logic, as below:
>>> objects = [-1, -5, 3]
>>> sorted(objects, key=abs)
[-1, 3, -5]
We can consider setting default arguments when we define our own functions. The theory is that if none of the arguments differ in most function calls, you should set these parameters with default values. Please note that these parameters are placed after other parameters that do not have a default value, as you have seen. sorted
Celebration.
When we use a new function, chances are we are unsure of the exact form of the arguments that the function takes. Consider the following function head which one can define:
def greeting(person, message):
pass
When you encounter this function, if you don’t see the implementation details, it has no clue what kind of argument you should be sending. It is possible that you can call this function like this:
greeting("John Smith", "Hi")
It is also possible that there is a class Person
and you are expected to call this function with an instance of Person
class, like below:
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
person = Person("John Smith")
greeting(person, "Hi")
As you can see, sometimes a function can confuse users. One way to remove such ambiguity is to implement type hints in the function. For example, if this function takes a string person
Logic, you can do this:
def greeting(person: str, message: str):
pass
Takes the example of the function if Person
Instead, you can also:
class Person:
passdef greeting(person: Person, message: str):
pass
By setting type hints in the function definition, one benefit that users can enjoy is meaningful indirection when they call your function in an IDE, such as PyCharm. A screenshot is given below:

PyCharm or any code analysis plugin in VSC uses type hints to analyze your code to provide hints.
Another thing to know is that if your function returns a value, you can provide type pointers for the return value, like below:
def greeting(person: Person, message: str) -> str:
return f"{message}, {person.first_name}!"
The format of the return type pointer is -> type
following parentheses in the head of the function.
Our functions usually involve a certain number of arguments. However, chances are that sometimes you may not know exactly what arguments users can send. use built-in print
Serves as an example, it can take any number of objects.
message0 = "Hello"
message1 = "World"
ending_symbol = "!"print(message0, message1, ending_symbol)
# output: Hello World !
why can we do this with print
Celebration? Let’s look at the calling signature:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
The reason we can print any number of objects is inherent in all *objects
parameter. Note that the parameter name has an asterisk prefix, which means that we can send a variable number of positional arguments to the function. As you can see, this improves the flexibility of print
Celebration. We can use this feature in our function.
def stringify(*objects) -> list[str]:
print(type(objects), objects)
return [str(object) for object in objects]
In a string function, we allow users to send a variable number of arguments, and we pass each argument to a . convert to str
Thing. One thing to note is that when users call this function with multiple positional arguments, these arguments are a . make up tuple
Thing.
In our example, objects
is one tuple
The object is such that we call it a. can use in for
loop, and we can verify this by calling this function with some arguments:
>>> stringify(1, (2, 4), False, {2, 3, 5, 7})
<class 'tuple'> (1, (2, 4), False, {2, 3, 5, 7})
['1', '(2, 4)', 'False', '{2, 3, 5, 7}']
Similarly, we can define a variable number of keyword arguments. This technique is usually abbreviated **kwargs
– You use two asterisks before the parameter name. When you see this in a function, it means that it can take any number of keyword arguments.
Consider the following example. We want to create a report card for a student’s courses, and we can come up with a function like the one below:
def create_report(name, **grades):
print(f"Grade Report for {name}")
for course, grade in grades.items():
print(f"{course}: {grade}")
Because a student can take different courses by using **grades
Provides such flexibility. As you can also see that grades
parameter is one dict
object, and you can access the item to access its key-value pairs and use them for
the noose. Some calling are shown below:
>>> create_report("John", math=95, chemistry=100, physics=98)
# output the following lines:
Grade Report for John
math: 95
chemistry: 100
physics: 98>>> create_report("Zoe", biology=93, geography=97)
# output the following lines:
Grade Report for Zoe
biology: 93
geography: 97
When you call this function, you list the arguments as keyword arguments, and Python treats these arguments as a . bundles as dict
The object used in the body of the function.
Although *args
And **kwargs
Provide flexibility to your function definition should you justify your uses, such as the usage scenarios discussed here. Namely, don’t abuse this feature, because named, fixed arguments are the most straightforward.
In this article, we reviewed three techniques you can consider when defining custom functions. When you use them in appropriate scenarios, you are making your functions easier to use.
Thank you for reading this article.
[ad_2]
Source link
#Define #Functions #Yong #Cui #July