7月2日Python基础学习笔记——嵌套函数、LEGB规则、类的定义、实例属性和实例方法等


前言

本文为7月2日Python基础学习笔记,分为十二个章节:

  • 嵌套函数(内部函数);
  • nonlocal 关键字:用于声明外层局部变量;
  • LEGB 规则;
  • 实操作业;
  • 面向对象和面向过程区别;
  • 对象的进化;
  • 类的定义;
  • __init__构造方法
  • 实例属性和实例方法;
  • 类对象、类属性、类方法、静态方法;
  • __del__方法(析构函数)和垃圾回收机制;
  • __call__方法。

一、嵌套函数(内部函数)

在函数内部定义的函数。
在以下情况下使用:

  • 封装 - 数据隐藏: 外部无法访问“嵌套函数;
  • 在函数内部避免重复代码:
def printChinesename(name, familyName):
	print("{0} {1}".format(familyName, name))

def printEnglishname(name, familyName):
	print("{0} {1}".format(name, familyName))
# 使用 1 个函数代替上面的两个函数
def printName(isChinese, name, familyName):
	def inner_print(a, b):
		print("{0} {1}".format(a, b))

	if isChinese:
		inner_print(familyName, name)

	else:
		inner_print(name, familyName)

printName(True, "小七", "高")
printName(False, "Donald", "Trump")

>>> 高 小七
>>> Donald Trump
  • 闭包。

二、nonlocal 关键字

# 使用 nonlocal 声明外层局部变量

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)

>>> inner b:  10
>>> outer b:  20
>>> a:  1000

三、LEGB 规则

Python 查找名称的规则:

Local–>Enclosed–>Global–>Built in

  • Local: 函数或者类的方法内部;
  • Enclosed: 嵌套函数;
  • Global: 全局变量;
  • Built in: Python 为自己保留的特殊名称。
# 测试 LEGB

str = "global"

def outer():
    str = "outer"

    def inner():
        str = "inner"
        print(str)

    inner()

outer()

# 依次注释掉 str = "inner", str = "outer", str = "global", 得到的结果如下

>>> inner
>>> outer
>>> global
>>> <class 'str'>

四、实操作业

1、定义一个函数实现反向输出一个整数。比如:输入 3245,输出 5

# 定义一个函数实现反向输出一个整数

def Reverse(n):
    s = str(n)
    print("该整数的反向整数为 {0}".format(int(s[::-1])))

n = input("输入一个整数:", )
Reverse(n)

>>> 输入一个整数:1234
>>> 该整数的反向整数为 4321

2、编写一个函数,计算下面的数列:

数列

# 编写一个函数,计算下面的数列:m(n) = 1/2 + 2/3 +……+n/(n+1)

def factorial(n):
    if n == 1:
        return 1/2
    else:
        return n/(n+1) + factorial(n-1)

result = factorial(3)
print(result)

>>> 1.9166666666666665

3、输入三角形三个顶点的坐标,若有效则计算三角形的面积;如坐标无效,则给出提示

def triangleArea(c):
    x = []
    y = []

    # 将列表 c 中的元素分别放到 x、y 列表中
    for i in range(len(c)):
        if i%2 == 0:
            x.append(c[i])
        else:
            y.append(c[i])

    return abs(x[0] * (y[1]-y[2]) + x[1] * (y[2]-y[0]) + x[2] * (y[0]-y[1]))/2

c = []

for i in range(6):
    s = input("依次输入三个顶点的坐标(以 Q 或 q 结束):")

    if s.upper() == 'Q':
        print("录入完成,退出")
        break

    c.append(float(s))

else:
    print("已录入三个顶点的坐标")

print("三角形面积为:{0}".format(triangleArea(c)))

依次输入三个顶点的坐标(以 Q 或 q 结束):0
依次输入三个顶点的坐标(以 Q 或 q 结束):1
依次输入三个顶点的坐标(以 Q 或 q 结束):0
依次输入三个顶点的坐标(以 Q 或 q 结束):0
依次输入三个顶点的坐标(以 Q 或 q 结束):1

>>> 已录入三个顶点的坐标
>>> 三角形面积为:0.5

4、输入一个毫秒数,将该数字换算成小时数,分钟数、秒数

def msToother(a):
    s = a/1000
    m = s/60
    h = m/60
    return s, m, h

a = float(input("输入一个毫秒数:"))

print("秒数为 {0:.2e},分钟数为 {1:.2e},小时数为 {2:.2e}".format(msToother(a)[0], msToother(a)[1], msToother(a)[2]))

>>> 输入一个毫秒数:2234
>>> 秒数为 2.23e+00,分钟数为 3.72e-02,小时数为 6.21e-04

五、面向对象和面向过程区别

  • Procedure Oriented:

    1. 更加关注程序的逻辑流程
    2. 执行者思维;
    3. 适合编写小规模的程序。
  • Object Oriented:

    1. 更加关注软件中对象之间的关系;
    2. 设计者思维;
    3. 适合编写大规模的程序。

六、对象的进化

简单数据(30、40)→ 数组([20, 30, 40])→ 结构体(不同类型的数据放到一起)→ 对象(更复杂的逻辑)

class Student:

    company = "SANY"   # 类属性
    count = 0    # 类属性

    def __init__(self, name, score): # 构造方法第一个参数必须为 self
        self.name = name # 实例属性
        self.score = score # 实例属性
        Student.count += 1

    def say_score(self): # 实例方法
        print("我的公司:", Student.company)
        print(self.name, "的分数是:", self.score)

s1 = Student("小李", 100) # #s1 是实例对象,自动调用__init__()方法
s1.say_score()

>>> 我的公司: SANY
>>> 小李 的分数是: 100

七、类的定义

把对象比作一个饼干类就是制造这个饼干的模具。
类的结构

  • 类定义数据类型的属性(数据)和方法(行为);
  • 类将行为和状态打包在一起;
  • 方法代码是共享的,属性数据不共享: 从一个类创建对象时,每个对象会共享这个类的行为(类中定义的方法),但会有自己的属性值(不共享状态);

八、__init__构造方法

一个 Python 对象包含如下部分:

  1. id;
  2. type;
  3. value:
    • 属性(attribute);
    • 方法(method)。

需要定义构造函数 __init__() 以创建对象。构造方法用于执行实例对象的初始化工作,即对象创建后,初始化当前对象的相关属性,无返回值。 要点如下:

  • 名称必须为 __init__()
  • 第一个参数固定,必须为:self

九、实例属性和实例方法

1、实例属性

  • 定义:

self.实例属性名 = 初始值

  • 访问:

self.实例属性名

  • 通过实例对象访问:

a = Student() # 创建对象,调用__init__()初始化属性
a.score = 100 # 可以给已有属性赋值,也可以新加属性

2、实例方法

  • 定义: 第一个参数必须为 self;
  • 调用: 不需要也不能给 self 传参。 self 由解释器自动传参。

十、类对象、类属性、类方法、静态方法

1、类对象

  • 测试类对象的生成:
class Student:
    pass  # 空语句

print(type(Student))
print(id(Student))

>>> <class 'type'>
>>> 1294042166464

2、类属性

类属性从属于类对象,可以被所有实例对象共享。

3、类方法 @classmethod

从属于“类对象”的方法。类方法通过装饰器**@classmethod** 来定义。要点如下:

  • @classmethod 必须位于方法上面一行;
  • 第一个 cls 必须有;cls 指“类对象”本身
  • 条用格式:类名.类方法名(参数列表)。参数列表中,不需要也不能给 cls 传值;
  • 类方法中访问实例属性和实例方法会报错;
class Student:

    company = "SANY"  # 类属性

    @classmethod
    def printCompany(cls):
        print(cls.company)

Student.printCompany()

>>> SANY

4、静态方法 @staticmethod

==Python 中允许定义与“类对象”无关的方法,称为“静态方法”。==要点如下:

  • @taticmethod 必须位于方法上面一行;

  • 调用格式: 类名.静态方法名(参数列表);

  • 静态方法中访问实例属性和实例方法会报错。

  • 静态方法使用测试:

class Student:
    company = "SANY"

    @staticmethod
    def add(a, b):
        print("{0} + {1} = {2}".format(a, b, (a+b)))
        return a + b

Student.add(20, 30)

>>> 20 + 30 = 50

5、内存分析实例对象和类对象创建过程

  • 类的整个创建过程:
class Student:

    company = "SANY"   # 类属性
    count = 0    # 类属性

    # 实例属性
    def __init__(self, name, score):
        self.name = name   # 实例属性
        self.score = score  # 实例属性
        Student.count += 1

    # 实例方法
    def say_score(self):
        print("我的公司:", Student.company)
        print(self.name, "的分数是:", self.score)

s1 = Student("小李", 100) #s1 是实例对象,自动调用__init__()方法
s1.say_score()
print('一共创建{0}个 Student 对象'.format(Student.count))

创建类的内存


十一、__del__方法(析构函数)和垃圾回收机制

  • 用于实现对象被销毁时所需的操作,如,释放对象占用的资源;
  • Python 实现自动的垃圾回收, 当对象没有被引用时(引用计数为 0),由垃圾回收器调用__del__方法。
class Person:

    def __del__(self):
        print("销毁对象{0}".format(self))

p1 = Person()
p2 = Person()
del p2
print("程序结束")

>>> 销毁对象<__main__.Person object at 0x0000020D6A9BB430>
>>> 程序结束
>>> 销毁对象<__main__.Person object at 0x0000020D6A9BB010>

十二、__call__方法和可调用对象

定义了__call__方法的对象,称为可调用对象即该对象可以像函数一样被调用。

class SalaryAccount:
    '''计算工资'''

    def __call__(self, salary):
        print("计算中……")
        yearSalary = salary * 12
        daySalary = salary//22.5
        hourSalary = daySalary//8

        return dict(yearSalary=yearSalary, daySalry=daySalary, hourSalary=hourSalary)

s = SalaryAccount()
print(s(30000))

>>> 计算中……
>>> {'yearSalary': 360000, 'daySalry': 1333.0, 'hourSalary': 166.0}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值