Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

1152-张同学

发表文章数:21

首页 » Python » 正文

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

嵌套函数

在函数内部定义的函数

def outer():
    print("outer")

    def inner():
        print("inner")

    inner()


outer()

一般在什么情况下使用嵌套函数?

  • 封装——数据隐藏

    外部无法访问“嵌套函数”;

  • 贯彻DRY(Don’t Repeat Yourself)原则

    嵌套函数,可以让我在函数内部避免重复代码;

  • 闭包

    后面会详解;

# 练习
def print_name(is_chinese, name, family_name):
    def inner_print(a, b):
        print("{0} {1}".format(a, b))

    if is_chinese:
        inner_print(family_name, name)
    else:
        inner_print(name, family_name)


print_name(True, "裤子", "彭")
print_name(False, "Alex", "Rose")

nonlocal关键字

  • nonlocal:用来声明外层的变量
  • global:用来声明全局变量
a = 100


def outer():
    b = 10

    def inner():
        nonlocal b  # 如果要在内部函数中对外部函数的变量进行就行,则需要通过nonlocal来声明,内部函数的b并不是局部变量
        print("inner:", b)
        b = 30

    inner()
    print("outer b:", b)

    global a  # 声明全局变量
    a = 200
    print(a)


outer()
print(a)  # 如不对global a进行声明,则此处a = 100

LEGB原则

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

# 此处注释掉,依然不报错,因为str()是python的内置函数
str = "global str"  # Global


def outer():
    str = "outer"  # Enclosed

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

    inner()


outer()

面向对象编程

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

面向对象和面向过程的区别

  • 面向过程(Procedure Oriented)思维

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 面向对象(Object Oriented)

    面向对(Object)思想更契合人的思维模式。我们首先思考的是“怎么设计这个事物?”比如思考造车,我们会先思考"车怎么设计",而不是“怎么按照步骤在造车的问题”。这就是思维方式的转变。

    Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 面向对象和面向过程的总结

    • 都是解决问题的思维方式,都是代码组织的方式
    • 解决简单问题可以使用面向过程
    • 解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程

对象的进化

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识
Day7:嵌套函数、LEGB规则,面向对象编程及类的初识
Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

类的定义

我们可以把类理解为制作事物的模具,而制作出来的事物就是对象。

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 对象是类的具体实体,一般称为“类的实例”,从一个类创建对象时,每个对象都会共享这个类的行为(类中定义的方法),但会有自己的属性值(不共享状态)。更具体一点:“方法的代码是共享的,属性数据不共享”。
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("彭裤子", 100)
s1.say_score()

构造函数 __ init __()

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识
​ 4.通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量。
Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

实例属性

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 当执行s1.age、s1.salary时,会在s1的内存空间增加这两个属性;
  • 当删除对象后del obj,从属与对象的属性,也会随之删除;

实例方法

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 定义实例方法时,第一个参数必须为self,和前面一样,self指当前的实例对象。
  • 调用实例方法时,不需要也不能给self传参,self由解释器自动传参。

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

  • 先通过a = Student()进行实例化,即在内存中开辟一块属于a的内存空间,a.say_score(60)相当于自动把a的内存地址(self)和需要传递的参数穿到类内存空间中对应的方法,进行调用。

  • 而Student.say_score(a),相当于直接在类的内存空间内调用say_score()方法,只不过穿的参数是对象a的内存地址,因此和上面的a.say_score(60)等效。

    Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

其他操作

  • dir(obj)可以获得对象的所有属性、方法
  • obj.__ dict __对象的属性字典
  • pass 空语句
  • isinstance(对象,类型) 判断“对象” 是不是“指定类型”
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("彭裤子", 100)
s1.say_score()

print(dir(s1))
'''
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'say_score', 'score']
'''
print(s1.__dict__)  # {'name': '彭裤子', 'score': 100}
print(isinstance(s1, Student)) # True

类对象

我们在前面讲的定义格式中,“class 类名:”。实际上,当解释器执行class语句时,就会创建一个类对象。

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

print(type(Student))  # <class 'type'>
print(type(s1))  # <class '__main__.Student'>
  • 各种的类,如Student都属于type类
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))


stu2 = Student  # 把类对象Student的地址给了stu2

s1 = Student("超载", 100)
s2 = stu2("地下婴儿", 90)

s1.say_score()  # 超载的分数是:100
s2.say_score()  # 地下婴儿的分数是:90

类属性和方法

类属性

类属性是从属于“类对象”的属性,也称为“类变量”。由于,类属性从属于类对象,可以被所有的实例对象共享。

  • 类属性的定义方式:

    • class 类名:
      • 类变量名 = 初始值

    在类中或者类的外面,我们可以通过:“类名.类变量名”来读写。

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

class Student:
    company = "STX"  # 类属性
    count = 0  # 类属性

    def __init__(self, name, score):
        self.name = name  # 实例属性
        self.score = score
        Student.count += 1  # 相当于计数器

    def say_score(self):  # 实例方法
        print("{0}的分数是:{1}".format(self.name, self.score))


s1 = Student("便利商店", "70")  # s1是实例对象,自动调用__init__()方法
s1.say_score()

s2 = Student("咖喱3000", 100)
s3 = Student("大波浪", 120)

print("一共创建{0}个student对象".format(Student.count))

类方法

  • 类的方法只从属于类本身。

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

class Student:
    company = "SXT"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def print_company(cls):
        print(cls.company)
        # print(self.name) 类方法与静态方法中,不能调用实例变量、实例方法


Student.print_company()

静态方法

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

# 静态方法
class Student:
    company = "SXT"

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


Student.print_company(20, 30)

__ del __()析构方法

Day7:嵌套函数、LEGB规则,面向对象编程及类的初识

class Person:

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


p1 = Person()  # 程序执行结束后,自动删除对象p1,所以又调用了def __del__()
p2 = Person()  # 先手动删除了p2:销毁对象<__main__.Person object at 0x0000019BFCE9FA20>
del p2
print("程序结束")
print(p2)  # NameError: name 'p2' is not defined
'''
销毁对象<__main__.Person object at 0x0000019BFCE9FA20>
程序结束
销毁对象<__main__.Person object at 0x0000019BFCC716A0>
'''

__ call __方法和可调用对象

定义了__ call __方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用

class SalaryAccount:

    def __call__(self, month_salary):
        print("算工资")
        year_salary = month_salary * 12
        day_salary = month_salary // 27.5
        hour_salary = day_salary // 8

        return dict(year_salary=year_salary, day_salary=day_salary, hour_salary=hour_salary)


s = SalaryAccount()
print(s(3000))

未经允许不得转载:作者:1152-张同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《Day7:嵌套函数、LEGB规则,面向对象编程及类的初识》 发布于2020-07-01

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录