在函数内部定义的函数
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")面向对象(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() 4.通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量。
先通过a = Student()进行实例化,即在内存中开辟一块属于a的内存空间,a.say_score(60)相当于自动把a的内存地址(self)和需要传递的参数穿到类内存空间中对应的方法,进行调用。
而Student.say_score(a),相当于直接在类的内存空间内调用say_score()方法,只不过穿的参数是对象a的内存地址,因此和上面的a.say_score(60)等效。
我们在前面讲的定义格式中,“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))定义了__ 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))