Python基础知识:函数

1、定义函数和调用函数

#定义函数def
def greet_user(username):
    '''简单的问候语'''
    print('Hello,%s!'%username)
greet_user('jack')#调用函数

2、形参和实参,实参的顺序很重要

def describe_flower(flower_type,flower_color='yellow'):
    print("My favorite flower is %s."%flower_type)
    print("My favorite %s is %s."%(flower_type,flower_color))
describe_flower('rose','red')
describe_flower(flower_type='lily',flower_color='white')
describe_flower(flower_type='babysbreath')#没有提供实参的形参将调用默认值
print('----------')

3、定义一个返回字典的函数

#返回字典
def make_album(singer_name,album_name,num_of_songs=''):
    info_of_album={'singer':singer_name,'album':album_name}
    if num_of_songs:
        info_of_album['number']=num_of_songs
    return info_of_album
album1=make_album('周杰伦','十一月的肖邦')
album2=make_album('许嵩','寻雾启事','12')
print(album1)
print(album2)

4、在函数中修改列表

def make_great(magicians):
    for i in range(len(magicians)):
        magicians[i] = 'The great ' + magicians[i]
    print(magicians)    
def show_magicians(magicians):
    for magician in magicians:
        print(magician)
mags = ['jack','alex','james']
make_great(mags)
show_magicians(mags)

5、[:]切片法创建列表副本,不改变原列表

def make_great(magicians,new_magicians):
    for i in range(len(magicians)):
        magicians[i] = 'The great ' + magicians[i]
        new_magicians.append(magicians[i])
    print(new_magicians)    
def show_magicians(magicians):
    for magician in magicians:
        print(magician)
mags = ['jack','alex','james']
new_mags = []
make_great(mags[:],new_mags)#函数调用列表副本
show_magicians(mags)
show_magicians(new_mags)

6、结合使用位置实参和任意数量实参,Python将先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中;*表示建立一个名为topping的空元组。

#将多余实参全部存放到空元组中
def make_sandwich(size,*toppings):
    print('I will make a %s-inch sandwich with the following toppings:'
    %str(size))
    for topping in toppings:
        print('- %s'%topping)
make_sandwich(12,'sausages')
make_sandwich(16,'sausages','mushrooms')

7、使用任意数量的关键字实参;**表示建立一个名为user_info的空字典

#将收到的所有键-值对都封装到这个字典中
def build_profile(first,last,**user_info):
    profile = {}
    profile['first_name'] = first
    profile['last_name'] = last
    for key,value in user_info.items():
        profile[key] = value
    return profile
user_profile = build_profile('james','lebran',
              location='shanghai',
              hobby='football')
print(user_profile)

8、import 调用模块中函数的几种方法

#导入整个模块,就可以使用模块中所有的函数
import func
func.make_car()
#导入特定的函数
from func import make_car
make_car()
#调用模块中的函数,并指定别名
from func import make_car as mc
car=mc('subaru','outback',color='blue',tow_package=True) 
print(car)
#调用模块中所有函数
from func import *   
make_sandwich(16,'sausages','mushrooms')

9、%运算符,相除返回余数

#--%--运算符
number = 10
print(number%2)
print(number%3)

10、运算符**表示乘方;2**3表示2的3次方

#for循环求64是2的几次方
a = 64
i = 0
for i in range(100):
    a /= 2
    i += 1
    if a == 1:
        print(i)
        break
#while循环求64是2的几次方
a = 64
i = 0
while True:
    a /= 2
    i += 1
    if a == 1:
        print(i)
        break
    else:
        continue

11、循环语句中的特殊语句

  • continue :跳出本次循环;

  • break:跳出所有循环;

  • 执行return之后,不再执行下面的代码,如果函数中没有return,Python将自动返回一个值None。

12、函数中的默认参数必须放到参数设置的末尾,例如def send(a,b,c="10")

13、元组动态参数*args的两种情况:

  • 第一种:实参不带*将实参放到args这个元组中,传递给函数,无论实参是一个列表还是字符串,都将作为元组的一个元素;

  • 第二种:实参带*,就把实参列表里的每个元素加入到元组中

def send(*args):
    print(args,type(args))
a = [11,22,'ddd']
send(a)
send(*a)

#([11, 22, 'ddd'],) <class 'tuple'>
#(11, 22, 'ddd') <class 'tuple'>

14、字典动态参数**args:默认将传入的参数,全部放入字典中。实参中必须包含key和value

def send(**args):
    print(args,type(args))
send(a=1,b=2)
dic = {'a':1,'b':2}
send(n=dic)
send(**dic)

#{'a': 1, 'b': 2} <class 'dict'>
#{'n': {'a': 1, 'b': 2}} <class 'dict'>
#{'a': 1, 'b': 2} <class 'dict'>

15、万能参数:同时使用*args和**kwargs:顺序不能反,一个*必须放在前面

def send(*args,**kwargs):
    print(args,type(args))
    print(kwargs,type(kwargs))
send(1,2,3,a='1',b='2')

#(1, 2, 3) <class 'tuple'>
#{'a': '1', 'b': '2'} <class 'dict'>

16、全局变量

  • 定义全局变量默认字母全部大写;

  • 如果想在函数中对全局变量重新赋值,需要加入global;

  • 如果全局变量是列表或字典,函数中可以修改全局变量,比如添加删除元素。

#全局变量,任何作用域都可以读取
NAME = 'alex'
def f1():
    print(NAME)
def f2():
    #修改全局变量
    global NAME
    NAME = 'alice'
    print(NAME)
def f3():
    print(NAME)
f1()
f2()
f3()

#alex
#alice
#alice

17、两个函数之间加两个空行,函数下面的波浪线就消失了,这样才符合函数的规范操作。

18、练习题:为每个函数添加注释要养成习惯,注释要放在双引号中,单引号会出现波浪线,不规范

def login(username,password):
    """
    用于用户登陆
    :param username: 用户输入的用户名
    :param password:用户输入的密码
    :return:True表示登陆成功,False表示登陆失败
    """
    t = open('text_file\KJ', 'r')
    for line in t:
        line_list = line.strip().split('|')
        if username == line_list[0] and password == line_list[1]:
            return True
    return False
def register(username,password):
    """
    用于用户注册
    :param username: 用户输入的用户名
    :param password: 用户输入的密码
    :return: 默认返回None
    """
    t = open('text_file\KJ', 'a')
    user_info = '\n' + username + '|' + password
    t.write(user_info)
    t.close()
def main():
    """
    让用户选择登陆或注册
    """
    user_input = input('1:登陆;2:注册:')
    if user_input == '1':
        user = input('请输入账户名:')
        pwd = input('请输入密码:')
        user_login = login(user,pwd)
        if user_login:
            print('登陆成功')
        else:
            print('登陆失败')
    elif user_input == '2':
        user = input('请输入账户名:')
        pwd = input('请输入密码:')
        register(user, pwd)
main()

19、lambda表达式

  • 就是简单函数的另一种表达方式,只能有一行

  • =前面是函数名,:前面是参数

#def函数
def f1(a):
    return a + 100
#lambda表达式
f2 = lambda a,b:a + b + 100
ret1 = f1(10)
print(ret1)
ret2 = f2(10,20)
print(ret2)
#设置默认值
f3 = lambda a,b=10:a + b + 100
ret3 = f3(10)
print(ret3)

20、Python内置函数

 

#abs( )--取绝对值
a = -1
print(abs(a))
#bool( )--返回布尔值(False:0,None,"",[],(),{})
print(bool(None))
#all( )--括号内接受一个可迭代的数据集,数据集中的每个元素都为真,函数的返回值才为True;
a = all([0,1,2,3])
print(a)
#any( )--括号内也是一个可迭代数据集,任意一个元素为真,就为真;
a = any([0,0,0,3])
print(a)
#ascii( )自动执行类的__repr__
class Name():
    def __repr__(self):
        return 'abc'
n = ascii(Name())
print(n)
#bin()接受一个十进制,转换成一个二进制
print(bin(8))#结果为0b1000,0b为二进制标识,8的二进制为1000
#oct()十进制转八进制
print(oct(9))#结果为0o11,0o标识八进制
#hex()十进制转十六进制
print(hex(15))#结果为0xf,0x标识十六进制
#UTF-8 一个汉字,三个字节,一个字节8位;
#gbk  一个汉字,两个字节;
#bytes(字符串,encoding=编码类型)把字符串转换为一个字节类型
s = "小明"
print(bytes(s,encoding='utf-8'))#b'\xe5\xb0\x8f\xe6\x98\x8e'
print(bytes(s,encoding='gbk'))#b'\xd0\xa1\xc3\xf7'
#bytearray()将每个字节存储为一个数组的元素
print(bytearray(s,encoding='utf-8'))
#字节类型转字符串,用同样的编码才能往回转换
n = bytes("小芳",encoding='utf-8')#字节类型
print(str(n,encoding='utf-8'))
#文件操作
filename = 'text_file\cats.txt'
with open(filename,'r') as f1:#只读
with open(filename,'w') as f2:#先清空文件,只写
with open(filename,'x') as f3:#文件存在,报错,不存在,创建并只写
with open(filename,'a') as f4:#追加内容
#读取文件时,出现乱码,很可能是编码语言选择错误
with open('text_file\word.txt','r',encoding='gbk') as f5:
     contents = f5.read()
     print(contents)
#rb,wb,xb,ab,r+b,w+b,x+b,a+b后面带b的,表示直接以字节的方式处理
with open(filename,'rb') as f:
    data = f.read()
     print(data,type(data))
#b'\xe5\xb0\x8f\xe7\xb1\xb3\r\n' <class 'bytes'>
#把二进制数据添加到文件,需要bytes先转换为字符串
 with open(filename,'ab') as f:
     data = f.write(bytes('小芳',encoding='utf-8'))
#f.seek(n)指针跳转到n指定的位置(字节)
#f.write()当前指针位置开始向后覆盖,n代表字节的位置
#f.tell()获取文件当前指针的字节位置
#r+,既能读,又能写;如果打开模式无b,read按照字符读取,有b,按字节
#无b,f.read(1)读取第一个字符,有b,读取第一个字节
with open('text_file\cats.txt','r+',encoding='utf-8') as f5:
     contents = f5.read(1)
     print(contents)#读取第一个字:小
#a+,无论你怎么调整指针位置,写入时都会写在最后
#w+,先清空内容,再写入,才能读取刚才写入的内容
#使用open,close,打开读写文件
 f = open(filename,'r')
 f.write('111')
 f.close()
# f.flush()强制刷入硬盘
# f.readable()是否可读
# f.readline()只读取一行
# f.seekable()指针是否可操作
# f.truncate()截断:把指针位置后面的数据都清空
# for line in f: 按行循环文件对象
# 同时打开两个文件,最后同时关闭
# 例如:想把一个文件的内容修改一个人名后写入另一个文件
 with open('db1','r') as f1,open('db2','a') as f2:
     for line in f1:
         new_line = line.replace('alex','alice')
         f2.write(new_line)
#将ascii码对照表里十进制转换为字母
r = chr(100)
print(r)#d
#将ascii码对照表里字母转换为十进制
n = ord("d")
print(n)#100
#random随机返回一串验证码;ascII码表里65-90为大写字母
import random
li = []
for i in range(4):
    r = random.randrange(0,5)
    if r == 1 or r == 3:
        num1 = random.randrange(0,10)
        li.append(str(num1))
    else:
        num2 = random.randrange(65,91)
        li.append(chr(num2))
print(li)
temp = ''.join(li)#join()把列表拼接成字符串
print(temp)
#compile()编译成Python代码
s = "print(123)"
r = compile(s,"<string>","exec")
#exec()执行Python代码;接受代码或者字符串,没有返回值
exec(r)
#eval()将字符串转换成Python代码,并获取结果
#函数只能执行表达式代码
r = "8*8"
ret = eval(r)
print(ret)
#dir()快速查看一个对象提供了哪些功能
print(dir(random))
#help()查看对象提供的详细功能
#divmod()接受两个整数,得到商和余数
#第一种,可以将返回值赋给两个变量
a,b = divmod(97,10)
print(a,b)
#第二种,可以当成一个元组
n = divmod(98,10)
print(n[0])
print(n[1])
#判断对象是否是某个类的实例
r = "abc"
print(isinstance(r,str))#True
'''filter(函数,可迭代的对象),循环第二个参数,
对参数的每一个元素执行函数,如果函数返回True,
就把这个元素加入结果,否则就舍弃
'''
def f(a):
    if a >2:
        return True
li = [1,2,3,4]
ret = filter(f,li)
print(list(ret))#记得要以列表的形式输出
#以lambda表达式实现
ret = filter(lambda a:a>3,li)
print(list(ret))
'''map(函数,可迭代的对象),循环第二个参数,
对参数的每一个元素执行函数,将函数返回值存放到结果
'''
li = [1,2,3]
ret = map(lambda a:a+100,li)
print(list(ret))#[101, 102, 103]
#globals()返回所有全局变量
#locals()返回所有局部变量
#hash()返回一个对象的hash值,一般用于存储字典的key
#id()查看内存地址
s = "sss"
print(id(s))#327689119312
#issubclass()判断一个类是否是另一个类的子类
#Python2中字符长度按字节来算,3中按字符来算
#len('小明')2中返回6,3中返回2
#pow(2,10)求2的10次方
#rount()四舍五入
#slice()切片
#zip()将列表的相同索引的值放到一个元组中
l1 = ['a',1,2]
l2 = ['b',1,2]
l3 = ['c',1,2]
r = zip(l1,l2,l3)
ret = list(r)[0]
print(' '.join(ret))

 21、装饰器:@函数名

  • 本质上就是函数,功能是为其他函数添加附加功能,前提是不改变装饰函数的源代码和调用方式;
  • 高阶函数+函数嵌套+闭包
  • 高阶函数:函数的参数或者返回值是一个函数名
  • 函数嵌套:在函数内部定义函数
  • 闭包:在一个作用域里放入定义变量,相当于打了一个包
  • @函数名 是python的一种语法糖
#函数名可以当做参数传递
def f1():
    print(123)
def f2(xx):
    xx()
f2(f1)#123
#装饰器@+函数名,有两个功能:
#1、自动执行outer函数并将其下面的函数名f1当做参数传递
#2、将outer函数的返回值重新赋值给f1=inner
#3、万能参数*args,**kwargs,接受任何数量的参数
def outer(func):
    def inner(*args,**kwargs):
        print("before")
        r = func(*args,**kwargs)
        print("after")
        return r
    return inner
@outer #相当于f1=outer(f1),返回的是inner的内存地址f1=inner,然后f1(args)执行inner(args)函数
def f1(args):
    print(args)
    return "fff" + args
ret = f1("ddd")#其实是在运行inner函数,最终得到inner函数的返回值
print(ret)

 22、生成器,有两种表达方式

  • 生成器表达式:m=(i for i in range(10))    m.__next__()

  • 生成器函数:其实就是由函数改造而来,具有生成能力的函数,标识:函数内部有yield,相当于return,但是可以执行多次

def func():
    print(111)
    yield 1
    print(222)
    yield 2
ret = func()#得到一个生成器
print(ret)#<generator object func at 0x00000061358BA138>
#进入函数执行函数,直到遇到yield,获取yield后面的数据,输出
r1 = ret.__next__()
print(r1)#111,1
r2 = ret.__next__()
print(r2)#222,2
#利用生成器创造一个循环函数
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        yield start
        start += 1
ret = myrange(3)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)

23、迭代器:就是一个封装了调用函数__next__的循环,让我们不用一步一步调用__next__函数

  • 凡是可作用于for循环的对象都是Iterable类型(可迭代对象);

  • 凡是可作用于next()函数的对象都是Iterator类型(迭代器对象),它们表示一个惰性计算的序列;

  • 生成器都是Iterator对象,生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了
  • 集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

  • Python的for循环本质上就是通过不断调用next()函数实现的;

24、递归:自己调用自己

#递归应用于用户重复登录
def login():
    inp = input("输入姓名")
    if inp == "admin":
        print("success")
    else:
        return login()
login()
#递归实现从1循环加到7
def add(n):
    n += 1
    if n <7:
        return add(n)
    else:
        return n
r = add(1)
print(r)#7
#递归实现1*2*3*4*5*6*7=5040
def mul(m,n):
    n += 1
    m *= n
    if n < 7:
        return mul(m,n)
    return m
ret = mul(1,1)
print(ret)#5040
#另一种方法
def func(num):
    if num == 1:
        return 1
    return num * func(num-1)
ret = func(7)
print(ret)

练习:递归实现斐波那契数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

25、反射

  • 利用字符串的形式去对象(模块)中(寻找/检查/删除/设置)成员

  • getattr()寻找、hasattr()检查、delattr()删除、setattr()设置

  • 通过字符串导入模块:

    • obj = __import__("xxx")

    • obj = __import__("file.xxx", fromlist=True)

def func():
    inp = input("请输入你要访问的URL(模块名/函数名):")
    #hasattr()检查对象中是否包含该成员,是返回True
    m, h = inp.split("/")
    #__import__通过字符串导入模块,obj.func()调用函数
    obj = __import__(m)
    #如果模块在文件夹中,后面加个参数fromlist,意思是按前面的指定路径导入
    #obj = __import__("lib." + m, fromlist=True)
    if hasattr(obj,h):
        #getattr()获取对象中的成员
        func = getattr(obj,h)
        func()
    else:
        print("404")

26、解压序列

a,b,c=(1,2,3)
a=1
b=2
c=3
#取开头和结尾的值
l=[1,2,3,4,5]
a,*_,b=l
a=1
b=5
#*加一个变量,可以是任意字符,表示中间的所有值

 27、冒泡算法

需求:请按照从小到大对列表 [13, 22, 6, 99, 11] 进行排序

思路:相邻两个值进行比较,将较大的值放在右侧,依次比较!

li = [13, 22, 6, 99, 11]
def func(arg):
    for i in range(1,len(arg)):
        for m in range(len(li) - i):
            if arg[m] > arg[m+1]:
                arg[m],arg[m+1] = arg[m+1],arg[m]
    print(arg)

func(li)

 28、列表转字典

status_choice = [(1, '上线'), (2, '下线')]

status_list = list(map(lambda x:{'id':x[0],'name':x[1]},Video.status_choice))

 

posted @ 2018-10-27 18:08  Charlie大夫  阅读(508)  评论(0编辑  收藏  举报