Python-100-Days: Day06 Functions and Modules

 函数的作用

编程大师Martin Fowler先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”,要写出高质量的代码首先要解决的就是重复代码的问题。可以将特定的功能封装到一个称之为“函数”的功能模块中,在需要的时候,我们只需要“调用”这个“函数”就可以了。

定义函数

在Python中可以使用def关键字来定义函数,和变量一样每个函数也有一个响亮的名字,而且命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,这一点和数学上的函数非常相似,程序中函数的参数就相当于是数学上说的函数的自变量,而函数执行完成后我们可以通过return关键字来返回一个值,这相当于数学上说的函数的因变量。

原始程序:

"""
输入M和N计算C(M,N)

Version: 0.1
Author: Maxwell
"""
m = int(input('m = '))
n = int(input('n = '))
fm = 1
for num in range(1, m + 1):
    fm *= num
fn = 1
for num in range(1, n + 1):
    fn *= num
fm_n = 1
for num in range(1, m - n + 1):
    fm_n *= num
print(fm // fn // fm_n)

对上述代码进行重构,在不影响代码执行结果的前提下对代码结构进行调整,重构后的代码如下:

"""
输入M和N计算C(M,N)

Version: 0.1
Author: Maxwell
"""
def fac(num):
    """求阶乘"""
    result = 1
    for n in range(1, num + 1):
        result *= n
    return result


m = int(input('m = '))
n = int(input('n = '))
# 当需要计算阶乘的时候不用再写循环求阶乘而是直接调用已经定义好的函数
print(fac(m) // fac(n) // fac(m - n))

函数的参数

函数是绝大多数编程语言中都支持的一个代码的"构建块",但是Python中的函数与其他语言中的函数还是有很多不太相同的地方,其中一个显著的区别就是Python对函数参数的处理。在Python中,函数的参数可以有默认值,也支持使用可变参数,所以Python并不需要像其他语言一样支持函数的重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式,下面是两个小例子。

 

from random import randint


def roll_dice(n=2):
    """摇色子"""
    total = 0
    for _ in range(n):
        total += randint(1, 6)
    return total


def add(a=0, b=0, c=0):
    """三个数相加"""
    return a + b + c


# 如果没有指定参数那么使用默认值摇两颗色子
print(roll_dice())
# 摇三颗色子
print(roll_dice(3))
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))

上面两个函数的参数都设定了默认值,意味着如果在调用函数的时候如果没有传入对应参数的值时将使用该参数的默认值,在上面的代码中我们可以用各种不同的方式去调用add函数,这跟其他很多语言中函数重载的效果是一致的。

其实上面的add函数还有更好的实现方案,在不确定参数个数时候,可以使用以下代码:

# 在参数名前面的*表示args是一个可变参数
def add(*args):
    total = 0
    for val in args:
        total += val
    return total


# 在调用add函数时可以传入0个或多个参数
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))

用模块管理函数

对于任何一种编程语言来说,给变量、函数这样的标识符起名字都是一个让人头疼的问题,因为我们会遇到命名冲突这种尴尬的情况。最简单的场景就是在同一个.py文件中定义了两个同名函数,由于Python没有函数重载的概念,那么后面的定义会覆盖之前的定义,也就意味着两个函数同名函数实际上只有一个是存在的。

def foo():
    print('hello, world!')


def foo():
    print('goodbye, world!')


# 下面的代码会输出什么呢?
foo()

当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为foo的函数,那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过import关键字导入指定的模块就可以区分到底要使用的是哪个模块中的foo函数,代码如下所示。

module1.py

def foo():
    print('hello, world!')

module2.py

def foo():
    print('goodbye, world!')

test.py

from module1 import foo

# 输出hello, world!
foo()

from module2 import foo

# 输出goodbye, world!
foo()

function1.py

 

"""
函数的定义和使用 - 计算组合数C(7,3)

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""

def factorial(n):
    result = 1
    for num in range(1, n+1):
        result *= num
    return result


print(factorial(7) // factorial(3) // factorial(4))

 function2.py

"""
函数的定义和使用 - 求最大公约数和最小公倍数

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""

def gcd(x, y):
    if x > y:
        (x, y) = (y, x)
    for factor in range(x, 1, -1):
        if x % factor == 0 and y % factor == 0:
            return factor
    return 1

def lcm(x, y):
    return x * y // gcd(x, y)

print(gcd(15, 27))
print(lcm(15, 27))

 

function3.py

 

"""
Python的内置函数
- 数学相关: abs / divmod / pow / round / min / max / sum
- 序列相关: len / range / next / filter / map / sorted / slice / reversed
- 类型转换: chr / ord / str / bool / int / float / complex / bin / oct / hex
- 数据结构: dict / list / set / tuple
- 其他函数: all / any / id / input / open / print / type

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""

def myfilter(mystr):
    return len(mystr) == 6

# help()
print(abs(-1.2345))
print(round(-1.2345))
print(pow(1.2345, 5))
fruits = ['orange', 'peach', 'durian', 'watermelon']
print(fruits[slice(1, 3)])
fruits2 = list(filter(myfilter, fruits))
print(fruits)
print(fruits2)

function4.py

"""
Python常用模块
- 运行时服务相关模块: copy / pickle / sys / ...
- 数学相关模块: decimal / math / random / ...
- 字符串处理模块: codecs / re / ...
- 文件处理相关模块: shutil / gzip / ...
- 操作系统服务相关模块: datetime / os / time / logging / io / ...
- 进程和线程相关模块: multiprocessing / threading / queue
- 网络应用相关模块: ftplib / http / smtplib / urllib / ...
- Web编程相关模块: cgi / webbrowser
- 数据处理和编码模块: base64 / csv / html.parser / json / xml / ...

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""

import time
import shutil


seconds = time.time()
print(seconds)
localtime = time.localtime(seconds)
print(localtime)
print(localtime.tm_year)
print(localtime.tm_mon)
print(localtime.tm_mday)
asctime = time.asctime(localtime)
print(asctime)
strtime = time.strftime('%Y-%m-%d %H:%M:%S', localtime)
print(strtime)
mydate = time.strptime('2018-1-1', '%Y-%m-%d')
print(mydate)

 function5.py

 

"""
函数的参数
- 位置参数
- 可变参数
- 关键字参数
- 命名关键字参数

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""


# 参数默认值
def f1(a, b=5, c=10):
    return a + b * 2 + c * 3


print(f1(1, 2, 3))
print(f1(100, 200))
print(f1(100))
print(f1(c=2, b=3, a=1))


# 可变参数
def f2(*args):
    sum = 0
    for num in args:
        sum += num
    return sum


print(f2(1, 2, 3))
print(f2(1, 2, 3, 4, 5))
print(f2())


# 关键字参数
def f3(**kw):
    if 'name' in kw:
        print('欢迎你%s!' % kw['name'])
    elif 'tel' in kw:
        print('你的联系电话是: %s!' % kw['tel'])
    else:
        print('没找到你的个人信息!')


param = {'name': 'Maxwell', 'age': 26}
f3(**param)
f3(name='Maxwell', age=26, tel='18766778899')
f3(user='Maxwell', age=26, tel='18766778899')
f3(user='Maxwell', age=26, mobile='18766778899')

function6.py

"""
作用域问题

Version: 0.1
Author: Maxwell
Date: 2024-04-29
"""

# 局部作用域
def foo1():
    a = 5

foo1()
# print(a)  # NameError

# 全局作用域
b = 10

def foo2():
    print(b)

foo2()

def foo3():
    b = 100     # 局部变量
    print(b)

foo3()
print(b)

def foo4():
    global b
    b = 200     # 全局变量
    print(b)

foo4()
print(b)

倘若您觉得我写的好,那么请您动动你的小手粉一下我,你的小小鼓励会带来更大的动力。Thanks.

### Exported Function Usage and Definition In programming, an exported function refers to a function that is made available outside its original module or file. This concept allows functions defined within one part of a program to be accessible from other parts of the application. #### Defining Exported Functions When defining an exported function in languages like JavaScript using ES6 modules, this involves explicitly exporting specific functions so they are visible externally: ```javascript // math.js export function add(a, b) { return a + b; } ``` For C/C++ environments, export mechanisms depend on platform-specific attributes or compiler directives such as `__declspec(dllexport)` for Windows DLLs or GCC's visibility attribute: ```cpp // mylib.h #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) #define EXPORT_API __declspec(dllexport) #else #define EXPORT_API #endif EXPORT_API int multiply(int x, int y); #ifdef __cplusplus } #endif ``` The above examples illustrate how different languages handle exposing internal implementations through exports[^1]. #### Using Exported Functions Once a function has been properly marked for export, another piece of software can import these symbols into their namespace. For instance, importing previously declared operations back into main files would look something like below depending upon language syntax rules: JavaScript example: ```javascript import {add} from './math'; console.log(add(5, 7)); // Outputs: 12 ``` Python equivalent might involve package imports where certain members have been designated public via `__init__.py` configuration files allowing selective exposure similarily but without explicit keywords required per item basis since everything not starting underscore by convention considered external API surface area unless otherwise stated privately inside class definitions etc... Go provides yet simpler approach with just capitalization indicating whether identifier (including functions) should appear publicly across packages boundaries automatically when referenced directly under same GOPATH workspace setup conventions followed during development phases ensuring proper linkage happens seamlessly between components written separately over time while maintaining clean separation concerns throughout large scale projects effectively leveraging modular design principles best practices recommended widely today among professional developers working collaboratively together towards common goals efficiently producing high quality maintainable source codes bases easier debugged tested deployed continuously integrated pipelines supporting rapid iterations cycles driven agile methodologies adopted industry wide nowadays more than ever before seen historically speaking considering evolution trends observed past decades regarding software engineering paradigms shifts occurring regularly adapting new tools techniques emerging constantly pushing forward state art always striving better solutions problems faced everyday challenges encountered real world scenarios requiring innovative thinking creative problem solving skills applied consistently achieve desired outcomes successfully meeting business objectives set forth stakeholders involved project lifecycles managed professionally end start points clearly defined understood agreed upon prior commencement activities undertaken teams assembled accordingly resources allocated appropriately timelines established realistic expectations maintained open communication channels kept active feedback loops encouraged constructive criticism welcomed positive reinforcement provided morale boosted productivity increased overall satisfaction levels achieved amongst participants contributing efforts collective success realized jointly shared rewards distributed fairly based contributions made individually recognized valued equally important aspects fostering collaborative work cultures promoting teamwork spirit essential ingredients recipe sustainable growth long term prosperity organizations seeking competitive advantages marketspace positioning themselves leaders forefront innovation waves sweeping industries transforming landscapes forever changing ways people interact technology shaping future possibilities beyond imagination limits expanding horizons uncharted territories explored boldly going places never gone before opening doors opportunities awaiting discovery creation next big things revolutionizing human civilization progress marching onward upward trajectory limitless potential awaits those daring enough venture out explore unknown frontiers courageously embracing change wholeheartedly adopting openness mindsets ready learn adapt overcome obstacles along journey self-discovery personal development intertwined closely technological advancements driving forces behind societal transformations witnessed unfolding rapidly accelerating pace unprecedented times we live currently experiencing firsthand history being made moment by moment day after day year following year marking milestones achievements celebrated globally communities coming together celebrate accomplishments honor pioneers trailblazers paving paths others follow suit inspired continue push boundaries further still reaching heights thought impossible yesterday becoming reality tomorrow thanks visionaries dreamers doers making dreams come true every single day tirelessly pursuing passions relentlessly chasing aspirations unwavering commitment excellence pursuit knowledge wisdom sharing freely generously helping lift everyone up collectively raising bar higher each step taken closer ultimate goal unity harmony coexistence planet Earth calls home sweet home indeed[^2]. --related questions-- 1. How does exporting differ between statically typed versus dynamically typed languages? 2. What considerations must be taken into account when deciding which functions to expose publicly within a library or framework? 3. Can you provide practical tips for organizing codebases around well-defined interfaces composed primarily of carefully selected exported entities? 4. Are there any performance implications associated with heavily relying on imported/exported functionalities rather than keeping logic contained locally within individual units/modules?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值