自定义函数
# 自定义函数
def 函数名(参数):
code...
code...
# 调用函数
函数名(参数)
定长参数
# 函数调用时,如果有位置参数时,位置参数必须在关键字参数(age=20)的前面
def user_info(name,age,gender):
print(f'名字是{name},年龄是{age},性别是{gender}')
user_info('雄安',age=20,gender=''女)
# 缺省参数
def user_info(name,age,gender='男'):
print(f'名字是{name},年龄是{age},性别是{gender}')
user_info('雄安',age=20)
user_info('雄安',age=20,gender=''女)
不定长参数
-
包裹位置传递(args 是一个元组)
不定长参数也叫可变参数。用于不确定调用时会传递多少个参数(不传参也行)的场景。此时可以用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组,args是元组类型,这就是包裹位置传递。
def user_info(*args):
print(args)
# ('tom',)
user_info('tom')
# ('tom',18)
user_info('tom',18)
- 包裹关键字传递(kwargs 是一个字典)
def user_info(**kwargs):
print(kwargs)
#{'name':'tom','age':18,'id':110}
user_info(name='tom',age=18,id=110)
综上:以上两种传递,都是一个组包的过程
文档注释
def sum_num1(a,b):
'''
求和函数sum_num1
param a:参数1
param b:参数2
return: 返回值
'''
return a + b
变量
修改自定义变量
# 错误示范
# 错误示范
# testA 中的 变量a只是局部变量,并不是全局变量
a = 100
def testA():
# 200
a = 200
print(a)
# 正确做法
# global关键字声明a是全局变量
# global a
# a = 200
def testB():
# 100
print(a)
testA()
testB()
交换变量
a,b = 1,2
a,b = b,a
print(a) # 2
print(b) # 1
引用
在python中,值是靠引用来传递的
我们可以用id()来判断两个变量是否为同一个值的引用。我们可以将id值理解为那块内存的地址标识
可变和不可变类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
列表为可变数据类型
lambda表达式(匿名函数)
lambda的参数形式
带判断的lambda
列表数据按字典key的值排序
x代表排序的数据,也就是每一个字典
高阶函数
abs() 绝对值
round() 四舍五入
内置高阶函数
reduce():累积:指的是运算,并不是乘
filter():过滤序列中不符合条件的元素
定义类
# 类名要满足标识符规则,同时遵循大驼峰命名习惯
class 类名():
code...
类属性(就是在pojo里定义一个变量)
类属性的优点:
- 记录的
某项数据始终保持一致
时。则定义类属性 - 实例属性要求每个对象为其单独开辟一份内存空间来记录数据,而类属性为全类所共有,仅占一份内存,更加节省内存空间
修改类属性
class Dog:
tooth = 10
# 10
print(Dog.tooth)
Dog.tooth = 20
# 20
print(Dog.tooth)
类方法
类方法特点:需要用装饰器@classmethod
来标识其为类方法,对于类方法,第一个参数必须是类对象
,一般以cls
作为第一个参数
类方法使用场景:
- 当方法中需要使用类对象(如访问私有类属性等)时,定义类方法
- 类方法一般和类属性配合使用
class Dog:
__tooth = 10
@classmethod
def get_tooth(cls):
return cls.__tooth
meili = Dog()
result = meili.get_tooth()
print(result)
静态方法
静态方法特点:
- 需要通过装饰器
@staticmethod
来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls) - 静态方法也能够通过实例对象和类对象去访问
静态方法使用场景:
- 当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗
class Dog:
@staticmethod
def info_print():
print('===')
wangcai = Dog()
# ===
wangcai.info_print()
# ===
Dog.info_print()
self(相当于java的this,谁调用就是谁)
self指的是调用该函数的对象
class Washer():
def wash(self):
print('洗衣服')
print(type(self) )
washer = Washer()
# 洗衣服
# <class '__main__.Washer'>
washer.wash()
class Washer():
# 类属性
width = 100
height = 500
def print_info(self):
print(self.width)
print(self.height)
washer = Washer()
# 100 500
washer.print_info()
washer.width = 200
washer.height = 1000
# 200 1000
washer.print_info()
魔法方法(具有特殊功能的函数)
init()作用:初始化对象
注意
该方法在创建对象时默认被调用,不需要手动调用
该方法中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去
class Washer():
def __init__(self):
self.width = 500
self.height = 800
def print_info(self):
print(f'宽是{self.width},高是{self.height}')
washer = Washer()
# 宽是500,高是800
washer.print_info()
带参数的_init_(),和java的构造函数类似
class Washer():
def __init__(self,width,height):
self.width = width
self.height = height
def print_info(self):
print(f'宽是{self.width},高是{self.height}')
washer = Washer(10,20)
# 宽是10,高是20
washer.print_info()
str()
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了_str_方法,那么就会打印从这个方法中return的数据
class Washer():
def __init__(self,width,height):
self.width = width
self.height = height
def __str__(self):
return str(self.width) + str(self.height)
washer = Washer(10,20)
# 1020
print(washer)
del():这个方法不需要手工调用,因为释放内存空间,解释器会自动调用
call()
# __call__()
# __call__()方法的作用其实是把一个类的实例化对象变成了可调用对象,
# 也就是说把一个类的实例化对象变成了可调用对象,只要类里实现了__call__()方法就行。
# 如当类里没有实现__call__()时,此时的对象p 只是个类的实例,不是一个可调用的对象,
# 当调用它时会报错:‘Person’ object is not callable.
# 使用callable()方法可以判断某对象是否可以被调用。
class People(object):
def __init__(self,name):
self.name=name
def __call__(self):
print("hello "+self.name)
a = People('无忌!')
# hello 无忌!
a()
# hello 无忌!
a.__call__()
print('----------------------------------------')
class Person(object):
def __init__(self,name):
self.name=name
a = Person('无忌!')
# TypeError: 'Person' object is not callable
a()
面向对象三大特征
- 封装
- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
- 继承
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
- 多态
- 传入不同的对象,产生不同的结果
继承(python有单继承和多继承)
python子类默认继承父类的所有属性和方法
单继承
class A:
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
class B(A):
pass
# 1
b = B()
b.info_print()
多继承
注意
当一个类有多个类的时候,默认使用第一个父类的同名属性和方法
子类和父类具有同名属性和方法,默认使用子类的同名属性和方法
重写
class School(object):
def __init__(self):
self.kongfu = 'gongfu'
def make_dinner(self):
print(self.kongfu)
class Master:
def __init__(self):
self.kongfu = 'shaolin'
def make_dinner(self):
print(self.kongfu)
class Prentice(School,Master):
def __init__(self):
self.kongfu = 'wudang'
def make_dinner(self):
print(self.kongfu)
# wudang
prentice = Prentice()
prentice.make_dinner()
子类调用父类同名方法和属性
一般应该是使用super()的,待研究
class School(object):
def __init__(self):
self.kongfu = 'gongfu'
def make_dinner(self):
print(self.kongfu)
class Master:
def __init__(self):
self.kongfu = 'shaolin'
def make_dinner(self):
print(self.kongfu)
class Prentice(School,Master):
def __init__(self):
self.kongfu = 'wudang'
def make_dinner(self):
# 如果先调用了父类的方法和属性,父类属性会覆盖子类属性,
# 故在调用属性前,先调用自己类的初始化
print(self.kongfu)
# 调用父类方法,为保证调用到的是父类的属性,
# 必须在调用方法前调用父类的初始化
def school_make_dinner(self):
School.__init__(self)
print(self.kongfu)
def master_make_dinner(self):
Master.__init__(self)
print(self.kongfu)
prentice = Prentice()
# wudang
prentice.make_dinner()
# gongfu
prentice.school_make_dinner()
# shaolin
prentice.master_make_dinner()
私有属性和私有方法
- 定义
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类
设置私有权限的方法:在属性名和方法名前面加两个_
class Person:
def __init__(self):
self.kongfu = 'stu'
self.__money = 200
# 获取私有属性
def get_money(self):
return self.__money
# 修改私有属性
def set_money(self,money):
self.__money = money
person = Person()
# stu
print(person.kongfu)
# 200
print(person.get_money())
person.set_money(300)
# 300
print(person.get_money())
多态
多态指的是一类事物有多种形态(一个抽象类有多个子类,因而多态的概念依赖于继承)
- 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化
- 实现步骤
- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行的效果是不同的
class Dog:
def work(self):
print('dog')
class PoliceDog(Dog):
def work(self):
print('PoliceDog')
class DrugDog(Dog):
def work(self):
print('DrugDog')
class Person():
def work_with_dog(self,dog):
dog.work()
person = Person()
policeDog = PoliceDog()
# PoliceDog
person.work_with_dog(policeDog)
异常
语法
try:
可能发生错误的代码
except:
如果出现异常执行的代码
捕获指定类型的异常
如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常
# 捕获一个指定类型的异常
try:
print(num)
except NameError:
print('有错误')
# 捕获多个指定类型的异常,捕获异常描述信息
try:
print(1/0)
except(NameError,ZeroDivisionError) as result:
print(result)
print('有错误')
# 捕获所有异常
try:
print(1/0)
except Exception as result:
print(result)
print('有错误')
没有异常要执行的代码
try:
print(1)
except Exception as result:
print(result)
else:
print('没有异常的时候执行的代码')
# 无论是否异常都要执行的代码
finally:
close()
自定义异常
在python中,抛出自定义异常的语法为raise
异常类对象
# 自定义异常,继承Exception
class ShortInputError(Exception):
def __init__(self,length,min_len):
self.length = length
self.min_len = min_len
# 设置抛出异常的描述信息
def __str__(self):
return f'你输入的长度是{self.length},不能少于{self.min_len}个字符'
def main():
try:
con = input('请输入密码:')
if len(con) < 3:
raise ShortInputError(len(con),3)
except Exception as result:
print(result)
else:
print('密码已经输入完成')
main()
模块
Python模块(Module),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句。
模块能定义函数,类和变量,模块里也能包含可执行的代码
导入模块的三种方法
# 方法一 import 模块名;模块名.功能
# import math
# 3.0 sqrt平方根
# print(math.sqrt(9))
# 方法二 from 模块名 import 功能1,功能2.。。;直接写函数/功能即可
# from math import sqrt
# 4.0
# print(sqrt(16))
# 方法三 from 模块名 import *;直接写函数/功能即可
from math import *
print(sqrt(25))
as定义别名
# 模块定义别名
import 模块名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名
制作模块
在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。
定义模块
新建一个Python文件,命名为my_module.py,并定义testA函数
def testA(a,b):
print(a + b)
模块定位顺序
当导入一个模块,Python解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录
- 如果都找不到,Python会查看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
注意
-
自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
-
使用from 模块名 import 功能的时候,如果功能名字重复,调用到的是最后定义或导入的功能
all列表
如果一个模块文件中有__all__变量,
当使用from xxx import * 导入时,只能导入这个列表中的元素
- cluTest模块/文件代码
__all__ = ['testA']
def testA():
print('testA')
def testB():
print('testB')
- 导入模块文件的代码
from cluTest import *
# testA
testA()
# NameError: name 'testB' is not defined
testB()
包
包将所有联系的模块组织在一起,即放到同一个文件夹下,
并且在这个文件夹创建一个名为 __init__.py文件,那么
这个文件夹就称之为包
制作包
New - Python Package - 输入包名 - 新建功能模块(有联系的模块)
注意:
新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为
导入包的方法
# 方法一:
# import 包名.模块名
# 包名.模块名.目标
import my_package.my_module
my_package.my_module.info_print()
# 方法二:
# 注意:必须在__init__.py文件中添加__all__ = [],
# 控制允许导入的模块列表
# from 包名 import *
# 模块名.目标
from my_package import *
my_module.info_print()
部分知识引用自:
https://blog.csdn.net/come_from_pluto