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

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原则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Imhzfzta-1593610575351)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701092821584.png)]

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


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

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

    inner()


outer()

面向对象编程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KNSaKvs0-1593610575355)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701095928229.png)]

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

  • 面向过程(Procedure Oriented)思维

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJdJKZ7e-1593610575356)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701100349934.png)]

  • 面向对象(Object Oriented)

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SSCFjnU-1593610575357)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701110603859.png)]

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

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

对象的进化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

类的定义

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqJ1haVQ-1593610575361)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701111731399.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZV8F0EFA-1593610575361)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701124731088.png)]
​ 4.通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量。
在这里插入图片描述

实例属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmwZt3QC-1593610575361)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701143515873.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZZ8KRGjV-1593610575362)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701144751131.png)]

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

实例方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d40jbj86-1593610575363)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701145255366.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgIyeV8Y-1593610575363)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701145536357.png)]

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g9aNhUrX-1593610575364)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701150329343.png)]

其他操作

  • 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语句时,就会创建一个类对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5mLj4aqA-1593610575364)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701152810897.png)]

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 类名:
      • 类变量名 = 初始值

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u1BH07h5-1593610575365)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701172212638.png)]

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))

类方法

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s62G30r7-1593610575365)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701172410705.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRyVfRJ3-1593610575365)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701172636034.png)]

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()

静态方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aXyjbabW-1593610575366)(C:\Users\z&y\AppData\Roaming\Typora\typora-user-images\image-20200701172744794.png)]

# 静态方法
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 __()析构方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMVY4zt1-1593610575366)(D:\xiao知识,xiao文化\python\新的篇章\笔记截图\20.png)]

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))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值