函数

返回值(斐波那契数列)

通过函数参数传入斐波那切数列长度,使用 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)

内置方法

Python基础语法下(查漏补缺版)_基础语法

Python基础语法下(查漏补缺版)_编程语言_02

(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 关键字。在类中,运算符对应类中的一些专有方法。因此运算符的重载实际上是对运算符对应的专有方法的重载。

Python基础语法下(查漏补缺版)_编程语言_03

# 函数__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 的文件夹

库强调的是功能性,而不是代码组织。通常将某个功能的“模块的集合”,称为库。

异常捕捉

Python基础语法下(查漏补缺版)_基础语法_04

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)  # 写入多行(数据)