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

    技术2022-07-11  76

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

    文章目录

    Day7:嵌套函数、LEGB规则,面向对象编程及类的初识嵌套函数一般在什么情况下使用嵌套函数? nonlocal关键字LEGB原则面向对象编程面向对象和面向过程的区别对象的进化 类的定义构造函数 __ init __()实例属性实例方法其他操作 类对象类属性和方法类属性类方法静态方法__ del __()析构方法 __ call __方法和可调用对象

    嵌套函数

    在函数内部定义的函数

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

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

    面向对象编程

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

    面向过程(Procedure Oriented)思维

    面向对象(Object Oriented)

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

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

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

    对象的进化

    类的定义

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

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

    ​ 4.通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量。

    实例属性

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

    实例方法

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

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

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

    其他操作

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

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

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

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

    类方法

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

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

    静态方法

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

    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))
    Processed: 0.012, SQL: 9