嵌套函数(内部函数):
在函数内部定义的函数为嵌套函数
外部无法调用内部函数
可以降低重复代码
闭包
# 嵌套函数
def o_f():
print('外层')
def i_f():
print('内层')
i_f()
# 练习
def printname(is_Chinese, first_name, last_name):
def inner_print(a, b):
print('{0} {1}'.format(a, b))
if is_Chinese:
inner_print(last_name, first_name)
else:
inner_print(first_name, last_name)
printname(True, 'Yihui', 'Yang')
printname(False, 'Yihui', 'Yang')
Yang Yihui
Yihui Yang
nonlocal关键字:
nonlocal用来声明外层的局部变量
global用来声明全局变量
# 测试nonlocal和global
def o_f():
b = 20
def i_f():
print('inner:', b) # 可以使用,不能修改
i_f()
print('outer:', b)
o_f()
inner: 20
outer: 20
def o_f():
b = 20
def i_f():
nonlocal b # 声明后可以修改
b = 10
print('inner:', b)
i_f()
print('outer:', b)
o_f()
inner: 10
outer: 10
LEGB规则:
Python在查找名称时,按照LEGB的规则查找,Local–>Enclosed–>Global–>Built in
Local:指函数或者类的方法内部
Enclosed:指的是嵌套函数
Global:指模块中的全局变量
Built in:指Python为自己保留的特殊名称
如果都没有则报错
# 测试
str = 'global'
def outer():
str = 'outer'
def inner():
str = 'inner'
print(str)
inner()
outer()
inner
str = 'global'
def outer():
str = 'outer'
def inner():
# str = 'inner'
print(str)
inner()
outer()
outer
str = 'global'
def outer():
# str = 'outer'
def inner():
# str = 'inner'
print(str)
inner()
outer()
global
# str = 'global'
def outer():
# str = 'outer'
def inner():
# str = 'inner'
print(str)
inner()
outer()
<class 'str'>
面向对象:
面向对象的编程是将数据和操作数据相关的方法封装到对象中
组织代码和数据的方式更接近人的思维
Python完全采用了面向对象的思想,在Python中,一切皆对象
Python支持面向对象,面向过程,函数式编程等多种编程范式
面向对象和面向过程的区别:
面向过程思维:更关注“程序的逻辑流程”,适合编写小程序,思考问题时按“怎样按步骤实现”,面向过程适合简单、不需要协作的事务
面向对象思维:更关注“软件中对象之间的关系”,适合编写大规模的程序,思考问题时首先思考“如何设计这个事务”而不是“步骤”
类(class):
如果把对象比作饼干,类就是制造饼干的模具
我们通过类定义数据类型的属性(数据/变量)和方法(行为/函数)
类名必须符合标识符规则,一般首字母大写,多个单词使用“驼峰原则”
类体中我们可以定义属性和方法
属性用来描述数据,方法(函数)用来描述这些数据相关操作
class Student:
def __init__(self, name, age): # self指当前对象本身,必须位于第一参数
self.name = name
self.age = age
def say_age(self):
print('{0} is {1} years old'.format(self.name, self.age))
s1 = Student('Y', 27)
s1.say_age()
Y is 27 years old
构造函数__init__():
第一个参数必须为self,可以更改名字,但一般不会改
通常用来初始化实例对象的实例属性,初始化指给实例属性赋值
通过class来调用构造函数,调用后,将创建好的对象返回给相应的变量
创建对象用__new__(),一般无需重新定义
实例属性:
是从属于实例对象的属性,也称为“实例变量”
一般在__init__()中通过 self.实例属性名 = 初始值 定义
在本类其他实例方法中,也通过self.实例属性名访问
创建实例对象后,通过实例对象访问:
test1 = Class()
test1.实例属性名 = 值
实例方法:
从属于实例对象的方法
def 方法名(self, [参数]):
函数体
# 练习
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def say_age(self):
print('{0} is {1} years old'.format(self.name, self.age))
s1 = Student('Y', 27)
Student.say_age(s1) # 解释器翻译格式
Y is 27 years old
dir()可以获取对象的所有属性,方法
s1.__dict__可以调用定义的属性,方法
pass 空语句
isInstance(s1, 对象)判断对象是否属于类
类对象:
在调用class时,创建了一个类对象
s2 = Student
print(s2())
类属性和类方法:
类属性是从属于类对象的属性,也成为类变量,被所有实例对象共享
通过 类名.类变量名 来读写
class Student:
score = 100 #类属性
def __init__(self, name, age): # self指当前对象本身,必须位于第一参数
self.name = name# 实例属性
self.age = age # 实例属性
def say_age(self):
print('{0} is {1} years old'.format(self.name, self.age))
print('成绩是{0}'.format(Student.score))
类方法:
从属于类对象的方法,通过装饰器‘@classmethod’来定义
@classmethod
def 类方法名(cls, [参数]):
函数体
# 练习
class Student:
score = 100
@classmethod
def print_score(cls):
print(cls.score)
Student.print_score()
静态方法:
在类里面定义与类无关的方法,需要通过类调用
@staticmethod
def 静态方法名([参数]):
函数体
# 练习
class Student:
score = 100
@staticmethod
def add(a, b):
print('{0}+{1}={2}'.format(a, b, (a+b)))
Student.add(8, 2)
类方法和静态方法中不能调用实例变量
析构函数__del__:
用于实现对象被销毁时所需的操作,比如释放占用资源等
Python实现自动的垃圾回收,当对象引用计数为0时,由垃圾回收器调用__del__
可调用对象和__call__方法:
定义了__call__方法的对象,称为可调用对象,即该对象可以向函数一样被调用
class SalaryCount:
def __call__(self, salary):
print('salary')
year_salary = salary*12
day_salary = salary//22.5
hour_salary = day_salary/8
return dict(year_salary = year_salary, month_salary = salary, day_salary = day_salary, hour_salary = hour_salary)
s = SalaryCount()
print(s(50000))