函数
返回值(斐波那契数列)
通过函数参数传入斐波那切数列长度,使用 return语句返回计算结果
#通过函数参数传入斐波那切数列长度,使用 return 语句返回计算结果
#定义函数
def fibs(n): #n 代码斐波那切数列的长度
#定义斐波那切数列的初识列表
result=[0,1]
# 通过循环计算,将结果添加到列表中
for x in range(n - 2):
result.append(result[-1] + result[-2])
# 将计算结果返回
return result
# 调用函数
re = fibs(100)
print('斐波那切数列:', re)
为函数添加文档注释
def print_star(n):
'''根据传入的 n,打印多个星号'''
print("*" * n)
# 使用函数的属性"__doc__"获取文档注释
print(print_star.__doc__)
print('+')
print('+')
print('+')
# 直接使用 help 函数获取函数的文档注释
help(print_star)
全局变量
# 定义全局变量
y = 100
def fun1(x):
return x + y
def fun2(x):
return x + y
# 调用函数
print(fun1(200))
print(fun2(200))
global 关键字
全局变量的作用范围是所有的函数都可用使用此变量,函数内要改变全局变量的值,使用 global 关键字。
a = 100 # 全局变量
def fun1():
global a # 如果要在函数内改变全局变量的值,增加 global 关键字声明
print(a) # 打印全局变量 a 的值
a = 300 # 修改全局变量的值
# 调用函数
fun1()
print(a)
变量的就近原则
a = 100 # 全局变量 a
def fun1():
a = 10 # 局部变量 a
print(a) # 打印变量 a 时候采用就近原则,则输出局部变量的 a
# 调用函数
fun1()
函数的参数
位置参数
def fun1(a, b, c):
print(a, b, c)
fun1(2, 3, 4)
fun1(3, 4) # 报错,位置参数不匹配
默认参数
def fun1(a, b, c=10, d=20):
print(a, b, c, d)
fun1(8, 9) # 参数 c 和 d 使用默认值
fun1(8, 9, 19) # 参数 d 使用默认值
fun1(8, 9, 19, 29)
def fun1(a=5, b=10, c=15, d=20):
print(a, b, c, d)
fun1(, , 19, 29) # 只想向最后两个参数传递值
def fun1(a=None, b=None, c=None, d=None):
if a == None:
a = 5
if b == None:
b = 10
if c == None:
c = 15
if d == None:
d = 20
print(a, b, c, d)
fun1(None, None, 19, 29) # a 和 b 使用默认值,给最后两个参数 c 和 d 传递值
关键字参数
def fun1(a, b, c):
print(a, b, c)
fun1(8, 9, 19) # 位置参数
fun1(c=10, a=20, b=30) # 命名参数,参数顺序可以和声明时的顺序不一致
可变参数
def fun1(a, b, *c): # 函数参数前添加一个"*",可变参数以元组形式体现
print(a, b, c)
fun1(8, 9, 19, 20)
def fun2(a, b, **c): # 函数参数前添加两个"**",可变参数以字典形式体现
print(a, b, c)
fun2(8, 9, name='gaoqi', age=18)
def fun3(a, b, *c, **d):
print(a, b, c, d)
fun3(8, 9, 20, 30, name='gaoqi', age=18)
强制命名参数
def fun1(*a, b, c):
print(a, b, c)
# fun1(2,3,4) #会报错。由于 a 是可变参数,将 2,3,4 全部收集。造成 b 和 c 没有赋值。
def fun2(a, *b, c):
print(a, b, c)
fun1(2, b=3, c=4) # 可变参数放在最前面,普通参数使用关键字参数形式传递
fun2('hello', 2, 3, 4, 5, c='end') # 可变参数放在中间,普通参数使用关键字参数形式传递
# 可变参数放在中间位置,调用函数时候不想使用关键字参数形式传递参数,
# 则普通参数必须有默认值
def fun1(a, *b, c=10, d=20):
print(a, b, c, d)
fun1('hello', 'Python', 'I', 'Love', 'You')
# 可变参数放在中间位置,调用函数时候不想使用关键字参数形式传递参数,
# 则普通参数必须有默认值,如果没有就报错,如下所示:
def fun1(a, *b, c, d):
print(a, b, c, d)
fun1('hello', 'Python', 'I', 'Love', 'You')
参数的传递
传递可变对象的引用
传递参数是可变对象(例如:列表、字典、自定义的其 他可变对象等),实际传递的 还是对象的引用。在函数体中 不创建新的对象拷贝,而是可 以直接修改所传递的对象。
b = [10, 20]
def fun2(m):
print("m:", id(m)) # b 和 m 是同一个对象
m.append(30) # 由于 m 是可变对象,不创建对象拷贝,直接修改这个对象
fun2(b)
print("b:", id(b))
print(b)
传递不可变对象的引用
传递参数是不可变对象(例如:int、float、字符串、 元组、布尔值),实际传递的 还是对象的引用。在”赋值操 作”时,由于不可变对象无法 修改,系统会新创建一个对象。
a = 100
def fun1(n):
print("n 的 id:", id(n)) # 传递进来的是 a 对象的地址
n = n + 200 # 由于 a 是不可变对象,因此创建新的对象 n
print("n 的 id:", id(n)) # n 已经变成了新的对象
print('n 的值:', n)
# 调用函数
fun1(a)
print("a 的 id:", id(a))
print('a 的值', a)
传递不可变对象包含的子对象是可变
a = (10, 20, [5, 6])
print("a 的 id:", id(a))
def test01(m):
print("m 的 id:", id(m))
m[2][0] = 888
print('m 元素的值:', m)
print("m 的 id:", id(m))
# 调用函数
test01(a)
print('a 列表的值:', a)
传递不可变对象时。不可变对象里面包含的子对象是可变的。则方法内修改了这个可变对象,原对象也发生了变化。
浅拷贝和深拷贝
其中浅拷贝指不拷贝子对象的 内容,只是拷贝子对象的引 用。而深拷贝会连子对象的内容也全部拷贝一份,对子对象的修改不会影响源对象。
浅拷贝
import copy
def testCopy():
'''测试浅拷贝'''
a = [10, 20, [5, 6]]
b = copy.copy(a)
print("a", a)
print("b", b)
b.append(30)
b[2].append(7)
print("浅拷贝......")
print("a", a)
print("b", b)
testCopy()
浅拷贝后,a 和 b 是一个独立的对象,但他们的子对象还是指向同一个对象;也就是说,不管是修改 a 列表还是 b 列表中的子对象元素, a 列表和 b 列表子对象元素都会同时改变。所以在 b[2]中添加元素,a 列表元素也会发生改 变。
深拷贝
import copy
def testDeepCopy():
'''测试深拷贝'''
a = [10, 20, [5, 6]]
b = copy.deepcopy(a)
print("a", a)
print("b", b)
b.append(30)
b[2].append(7)
print("深拷贝......")
print("a", a)
print("b", b)
testDeepCopy()
深度拷贝后, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。所以在 b[2]中添加元素,a 列表元素不会发生改变。
嵌套函数(内部函数)
# 内部函数引用外部函数的变量
def func():
a=10
b=20
x=30
y=40
def sum():
return a+b
def sub():
return y-x
return sum()*sub()
#调用外部函数
print(func())
nonlocal 关键字
# 测试 nonlocal、global 关键字的用法
a = 100 # 全局变量
def outer():
b = 10 # 外部函数的变量
def inner():
nonlocal b # 声明外部函数的局部变量
print("inner b:", b)
b = 20 # 对外部函数的变量重新赋值
global a # 声明全局变量
a = 1000 # 对全局变量重新赋值
inner()
print("outer b:", b)
outer()
print("a:", a)
递归
# 使用递归函数计算阶乘(factorial)
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
# 计算 1 到 5 的阶乘
for i in range(1, 6):
print(i, '!=', factorial(i))
eval()函数
eval() 函数实现 list、dict、tuple 与 str 之间的转化
# 字符串转换成列表
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
print(type(a)) # 查看 a 的类型
b = eval(a) # 将字符串转换为列表
print(b)
# 字符串转换成字典
a = "{1: 'a', 2: 'b'}"
print(type(a))
b = eval(a)
print(type(b))
print(b)
# 字符串转换成元组
a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
print(type(a))
b = eval(a)
print(type(b))
print(b)
eval() 函数用来执行一个字符串表达式,并返回表达式的值
# eval()函数执行一个字符串表达式
s = eval('2 + 2') # 将 string 变成算术表达式来执行
print(s)
a = 10
b = 20
c = eval("a+b")
print(c)
dict1 = dict(a=100, b=200)
d = eval("a+b", dict1)
print(d)
# eval()函数表达式不可计算直接返回结果
s = '["a","b","c"]'
print(eval(s))
面向对象编程
面向对象编程将数据和操作数据相关的方法封装到对象中,组织代码和数据的方式更加接近人的思维,从而大大提高了编程的效率。Python完全采用了面向对象的思想,是真正面向对象的编程语言,完全支持面向对象的基本功能,例如:封装,继承与多态等。Python支持面向过程,面向对象,函数式编程等多种编程范式。
类的定义
# 定义 Student 类
class Student:
def __init__(self, name, score): # 构造方法第一个参数必须为 self
self.name = name # 实例属性
self.score = score
def say_score(self): # 实例方法
print(self.name, '的分数是:', self.score)
s1 = Student('张三', 80) # s1 是实例对象,自动调用__init__()方法
s1.say_score()
创建对象
# 定义 Student 类
class Student:
def __init__(self, name, score): # 构造方法第一个参数必须为 self
self.name = name # 实例属性
self.score = score
# 创建对象 s1,调用__init__()方法,参数匹配
s1 = Student('张三', 80)
print(s1)
s2 = Student() # 参数不匹配,报错
实例属性
# 定义 Student 类
class Student:
def __init__(self, name, score): # 构造方法第一个参数必须为 self
self.name = name # 实例属性
self.score = score
def say_score(self): # 实例方法
# 在实例方法中访问实例属性
print(self.name, '的分数是:', self.score)
s1 = Student('张三', 80) # s1 是实例对象,自动调用__init__()方法
s1.say_score() # 调用实例方法
# 给已有实例属性重新赋值
s1.name = '李四'
s1.score = 98
print(s1.name, '的分数是:', s1.score)
实例方法
class Student:
def __init__(self, name, score):
self.name = name # 实例属性
self.score = score
def say_score(self): # 实例方法
print('{0}的分数是{1}'.format(self.name, self.score))
s1 = Student('张三', 80) # s1 是实例对象,自动调用__init__()方法
# 调用实例方法
s1.say_score()
s2 = Student('李四', 89) # s2 是实例对象,自动调用__init__()方法
# 调用实例方法
s2.say_score()
类属性
class Student:
company = "华为" # 类属性
count = 0 # 类属性
def __init__(self, name, score):
self.name = name # 实例属性
self.score = score
Student.count = Student.count + 1
def say_score(self): # 实例方法
print("我的公司是:", Student.company)
print(self.name, '的分数是:', self.score)
s1 = Student('Windstorm', 420) # s1 是实例对象,自动调用__init__()方法
s1.say_score()
print('一共创建{0}个 Student 对象'.format(Student.count))
类方法
类方法是从属于“类对象”的方法。类方法通过装饰器@classmethod 来定义
cls 指的就是“类对象”本身
class Student:
company = "SXT" # 类属性
@classmethod
def printCompany(cls):
print(cls.company)
Student.printCompany()
上下对比体会:
class Student:
company = "SXT" # 类属性
def printCompany(cls):
print(cls.company)
Student().printCompany()
class Student:
company = "SXT" # 类属性
@classmethod
def printCompany(cls, com, uid):
print(cls.company, com, uid) # company是类方法,而cls就是指类对象本身,所以调用类方法是必须加上
Student.printCompany("jisuanji", 23324)
# ---------------------------对比---------------------
class Student:
company = "SXT" # 类属性
@classmethod
def printCompany(cls, com, uid):
print(company, com, uid)
Student.printCompany("jisuanji", 23324)
静态方法
Python 中允许定义与“类对象”无关的方法,称为“静态方法”。“静态方法”和在模块中定义普通函数没有区别,只不过“静态方法”放到了“类的名字空间里面”,需要通过“类调用”。
class Student:
company = "SXT" # 类属性
@staticmethod
def add(a, b): # 静态方法
print("{0}+{1}={2}".format(a, b, (a + b)))
return a + b
Student.add(20, 30)
内置方法
(1)__del__方法(析构函数)
由于 Python 中定义了__del__()的实例将无法被 Python 循环垃圾收集器(gc)收集,所以建议只有在需要时才定义__del__()。下 面演示 Python 的函数__del__()的使用
# 析构函数
class Person:
def __del__(self):
print("销毁对象:{0}".format(self))
p1 = Person()
p2 = Person()
del p2
print("程序结束")
(2) __str__()
如果希望使用 print 输出对象的描述信息,且能够打印自定义内容,可以使用 str 内置方法
class Student:
def __init__(self, name, score):
self.name = name # 实例属
self.score = score
def __str__(self):
return '{0}的分数是{1}'.format(self.name, self.score) # 返回一个字符串
s1 = Student('张三', 80) # s1 是实例对象,自动调用__init__()方法
print(s1) # 输出 s1 对象时候,调用__str__()方法
(3) __call__()
定义了__call__方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用。
# 测试__call__,可调用对象
class SalaryAccount:
'''工资计算类'''
def __call__(self, salary):
yearSalary = salary * 12
daySalary = salary // 30
hourSalary = daySalary // 8
return dict(monthSalary=salary, yearSalary=yearSalary, daySalary=daySalary, hourSalary=hourSalary)
s = SalaryAccount()
print(s(5000)) # 可以像调用函数一样调用对象的__call__方法
运算符重载
由于在 Python 中,运算符都有其对应的函数。因此在 Python 中,运算符重载不需要像在 C++中那样使用 operator 关键字。在类中,运算符对应类中的一些专有方法。因此运算符的重载实际上是对运算符对应的专有方法的重载。
# 函数__add__()的使用
a = 20
b = 30
c = a + b
d = a.__add__(b)
print("c=", c)
print("d=", d)
#测试运算符的重载
class Person:
def __init__(self,name):
self.name = name
def __add__(self, other):
if isinstance(other,Person):
return "{0}--{1}".format(self.name,other.name)
else:
return "不是同类对象,不能相加"
def __mul__(self, other):
if isinstance(other,int):
return self.name*other
else:
return "不是同类对象,不能相乘"
p1 = Person("高淇")
p2 = Person("高希希")
x = p1 + p2 #调用 __add__()方法
print(x)
print(p1*3) #调用__mul__()方法
私有属性和私有方法
# 测试私有属性和私有方法
class Employee:
__company = "百战程序员" #私有类属性.
def __init__(self,name,age):
self.name = name
self.__age = age #私有实例属性
def say_company(self):
#类内部可以直接访问私有属性
print("我的公司是:",Employee.__company)
print(self.name,"的年龄是:",self.__age)
self.__work() #类内部可以直接访问私有方法
def __work(self): #私有实例方法
print("工作!好好工作!")
p1 = Employee("高淇",32)
print(p1.name)
p1.say_company()
print(p1._Employee__age) #通过这种方式可以直接访问到私有属性
p1._Employee__work() #通过这种方式可以直接访问到私有方法
# print(p1.__age) #直接访问私有属性,报错
# p1.__work() #直接访问私有方法,报错
方法没有重载
Python 中是没有方法的重载的。定义一个方法即可有多种调用方式,相当于实现了其他语言中的方法的重载。 如果在类体中定义了多个重名的方法,只有最后一个方法有效。
#Python 中没有方法的重载。定义多个同名方法,只有最后一个有效
class Person:
def say_hi(self):
print("hello")
def say_hi(self,name,age):
print("姓名:{0},年龄:{1}".format(name,age))
p1 = Person()
p1.say_hi("张三",23)
p1.say_hi() #不带参,报错
获取对象信息
type()函数
print(type(123))
print(type('123'))
print(type(None))
isinstance()函数
a = 5
print(isinstance(a, int)) # True
print(isinstance(a, str)) # False
print(isinstance(a, (str, int, list))) # 是元组中的一个返回 True
type() 不会认为子类是一种父类类型,不考虑继承关系。isinstance() 会认为子类是一种父类类型,考虑继承关系。如果要判断两个类型是否相同推荐使用 isinstance()。
class A:
pass
class B(A): # 继承 A
pass
print(isinstance(A(), A)) # 执行结果 True
print(type(A()) == A) # 执行结果 True
print(isinstance(B(), A)) # 执行结果 True
print(type(B()) == A) # 执行结果 False
dir()函数
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包 含__dir__(),该方法将最大限度地收集参数信息。
print(dir('abc'))
@property 装饰器
# @property 装饰器的使用
class Student(object):
@property
def score(self):
return self.__score
@score.setter
def score(self, value):
if not isinstance(value, int):
print('成绩必须是整数')
else:
if value < 0 or value > 100:
print('成绩必须在 0-100 之间')
else:
self.__score = value
s = Student()
s.score = 60 # 实际转化为 s.set_score(60)
print('获取的成绩是:', s.score) # 实际转化为 s.get_score()
s.score = 1000
s.score = 'abc'
通过使用@property,可以对实例属性不直接暴露,如果想定义只读属性,则只定义 getter方法,不定义 setter 方法就是一个只读属性,示例代码如下:
import datetime
class Student(object):
@property
def birth(self):
return self.__birth
@birth.setter
def birth(self, value):
self.__birth = value
@property
def age(self):
# 获取当前年份
now_year = datetime.datetime.now().strftime('%Y')
return int(now_year) - int(self.__birth)
s = Student()
s.birth = '2002' # 设置出生年份
print('出生日期:', s.birth) # 获取出生年份
print('年龄:', s.age) # 获取年龄
面向对象三大特征
封装
隐藏对象的属性和实现细节,只对外提供必要的方法。相当于将“细节封装起来”,只对外暴露“相关调用方法”。 上面学习的“私有属性、私有方法”的方式,实现“封装”。Python 追求简洁的 语法,没有严格的语法级别的“访问控制符”,更多的是依靠程序员自觉实现。
继承
继承的实现
class Person:
def sing(self):
print('人在唱歌')
class Student(Person):
def dance(self):
print('学生在跳舞')
s1 = Student()
s1.sing() # 调用父类的方法
s1.dance()
# 子类中显示调用父类的构造方法
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def say_age(self):
print(self.name, "的年龄是:", self.__age)
class Student(Person):
def __init__(self, name, age, score):
self.score = score
# 子类并不会自动调用父类的__init__()构造方法,需要显式的调用
Person.__init__(self, name, age)
s1 = Student("张三", 15, 85)
s1.say_age()
方法的重写
子类继承了父类除构造方法之外的所有成员,如果 父类中方法的功能不能满足 子类的需求,子类可以重写父类的方法。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_age(self):
print("年龄:", self.age)
def say_name(self):
print("姓名:", self.name)
class Student(Person):
def __init__(self, name, age, score):
self.score = score
Person.__init__(self, name, age) # 构造函数中包含调用父类构造函数
def say_score(self):
print("分数是:", self.score)
# 重写父类的方法
def say_name(self):
print("报告老师,我是", self.name)
s1 = Student("张三", 15, 85)
s1.say_score()
s1.say_name()
s1.say_age()
检测继承关系
class Person(object):
pass
class Child(Person): # Child 继承 Person
pass
class GrandSon(Child):
pass
# 要判断 B 是否是 A 的父类可以使用issubclass函数
# 第 1 个参数是子类、第 2 个参数是父类。如果第 1 个参数指定的类与第 2 个参数
# 指定的类确实是继承关系,那么该函数返回 True,否则返回False
print(issubclass(Child, Person)) # True
print(issubclass(GrandSon, Person)) # True
多继承
#多重继承
class A:
def aa(self):
print("aa")
class B:
def bb(self):
print("bb")
class C(B,A):
def cc(self):
print("cc")
c = C()
c.cc()
c.bb()
c.aa()
查看类的继承层次结构
通过类的方法 mro()或者类的属性__mro__可以输出这个类 的继承层次结构。
class A:
pass
class B(A):
pass
class C(B):
pass
print(C.mro())
MRO()
MRO(Method Resolution Order)指方法解析顺序。Python 支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将“从左向右”按顺序搜索。可以通过 mro()方法获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的。
# 多重继承
class A:
def aa(self):
print("aa")
def say(self):
print("say AAA!")
class B:
def bb(self):
print("bb")
def say(self):
print("say BBB!")
class C(B, A):
def cc(self):
print("cc")
c = C()
print(C.mro()) # 打印类的层次结构
# 解释器寻找方法是“从左到右”的方式寻找,此时会执行 B 类中的 say()
c.say()
super()
在子类中,如果想要获得父 类 的 方 法 时 , 可 以 通 过 super()。
# super()
class A:
def say(self):
print("say AAA")
class B(A):
def say(self):
A.say(self) # 调用父类的 say 方法
super().say() # 通过 super()调用父类的方法
print("say BBB")
b = B()
b.say()
多态
多态是方法的多态,不是属性的多态(多态与属性无关)。多态的存的必要条件:继承,方法重写。
#多态
class Animal:
def shout(self):
print("动物叫了一声")
class Dog(Animal):
def shout(self):
print("小狗,汪汪汪")
class Cat(Animal):
def shout(self):
print("小猫,喵喵喵")
def animalShout(a):
if isinstance(a,Animal):
a.shout() #传入的对象不同,shout 方法对应的实际行为也不同。
animalShout(Dog())
animalShout(Cat())
上面的代码展示了多态最为多见的一种用法,即父类引用做方法的形参,实参可以是任意的子类对象,可以通过不同的子类对象实现不同的行为方式。
对象的深拷贝和浅拷贝
# 测试对象的引用赋值、浅拷贝、深拷贝
import copy
class MobilePhone:
def __init__(self, cpu, screen):
self.cpu = cpu
self.screen = screen
class CPU:
def calculate(self):
print("CPU 对象:", self)
class Screen:
def show(self):
print("屏幕对象:", self)
c = CPU()
s = Screen()
m = MobilePhone(c, s)
print('------浅拷贝-------')
m2 = copy.copy(m) # m2 是新拷贝的另一个手机对象
m.cpu.calculate()
m2.cpu.calculate() # m2 和 m 拥有了一样的 cpu 对象和 screen 对象
m.screen.show()
m2.screen.show()
print('------深拷贝-------')
m3 = copy.deepcopy(m)
m.cpu.calculate()
m3.cpu.calculate() # m3 和 m 拥有不一样的 cpu 对象和 screen 对象
m.screen.show()
m3.screen.show()
设计模式
单例模式
单 例 模 式 ( Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个 实例存在。并且提供一个访问该实例的全局访问点。单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个“单例对象”,然后永久驻留内存中,从而极大的降低开销。__new()__方法在__init()__方法之前被调用,用于创建实例对象。利用这个方法和类属性的特性可以实现设计模式中的单例模式,示例如下:
# 单例模式
class MySingleton:
__instance = None
def __new__(cls, *args, **kwargs): # 重写__new__()方法
if cls.__instance == None:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, name):
self.name = name
a = MySingleton("aa")
print(a)
b = MySingleton("bb")
print(b)
c = MySingleton("cc")
print(c)
在上面的代码中,定义了私有的类属性__instance,初始值为 None。__instance 的值是第 1 次创建的实例,以后的实例化操作都将共享这个属性。因此,就达到了创建唯一实例的 目的。
工厂模式
所谓工厂模式就是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。 工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进 行统一的管理和控制.
#工厂模式
class CarFactory:
def createCar(self,brand):
if brand == "奔驰":
return Benz()
elif brand == "宝马":
return BMW()
elif brand == '比亚迪':
return BYD()
else:
return "未知品牌,无法创建"
class Benz:
def run(self):
print('奔驰在马路上...')
class BMW:
def run(self):
print('宝马在马路上...')
class BYD:
def run(self):
print('比亚迪在马路上...')
factory = CarFactory()
c1 = factory.createCar("奔驰")
c2 = factory.createCar("宝马")
c1.run()
c2.run()
在上面的代码中,有了 CarFactory 类后,就可以通过向固定的接口传入参数获得想要的对象实例,从而创建了奥迪车、比亚迪车、宝马车。
模块
Python 模块(Module)是一个 Python 文件,以 .py 作 为后缀结尾的文件,通常包含 了 Python 对 象 定 义 和 Python 语 句 。 模 块 内 的 Python 代码通常是按照一定逻辑组织起来的,把相关的代码分配到一个模块里能让你的代码更好用,更易懂,更有可维护性。模块内可以定义函数、类、变量。当然,模块里也能包 含可执行的代码。 导入模块的方式主要有三种,分别是:
□ import 模块名
□ from 模块名 import 函数名
□ from 模块名 import *
#导入模块
import math
#查看模块
print(dir(math))
包
当一个项目中有很多个模块时,需要再进行组织。将 功能类似的模块放到一起, 形成了“包”。本质上“包” 就是一个必须有__init__.py 的文件夹
库
库强调的是功能性,而不是代码组织。通常将某个功能的“模块的集合”,称为库。
异常捕捉
JSON 字符串与字典互相转换
import json
d = {"name": "zs", "age": 23, "sex": "man"}
# 将字典转换为 json 字符串
jsonString = json.dumps(d)
# 输出 jsonString 变量的类型
print(type(jsonString))
# 输出 JSON 字符串
print(jsonString)
print('使用 loads 函数将 JSON 字符串转换为字典')
# 使用 loads 函数将 JSON 字符串转换为字典
d = json.loads(jsonString)
print(type(d))
# 输出字典
print(d)
print('eval 函数使用 eval 函数将 JSON 字符串转换为字典')
# 使用 eval 函数将 JSON 字符串转换为字典
dd = eval(jsonString)
print(type(dd))
print(dd)
CSV 文件操作
csv.reader 对象从 csv 文件读取
import csv
with open(r"d:\a.csv") as a:
a_csv = csv.reader(a) #创建 csv 对象,它是一个包含所有数据的列表,每一行为一个元素
headers = next(a_csv) #获得列表对象,包含标题行的信息
print(headers)
for row in a_csv: #循环打印各行内容
print(row)
csv.writer 对象写入
import csv
headers = ["工号", "姓名", "年龄", "地址", "月薪"]
rows = [("1001", "高淇", 18, "西三旗 1 号院", "50000"), ("1002", "高八", 19, "西三旗 1 号院", "30000")]
with open(r"./b.csv", "w", newline='') as b:
b_csv = csv.writer(b) # 创建 csv 对象
b_csv.writerow(headers) # 写入一行(标题)
b_csv.writerows(rows) # 写入多行(数据)