1.nonlocal 关键字
注释:nonlocal:用来声明外层的局部变量。
          global:用来声明全局变量。
例如:
def outer():
    b = 10
    def inner():
        nonlocal b       #声明外部函数的局部变量
        print("inner:",b)
        b = 20
    inner()
    print("outer b:",b)
outer()

解释:在内层函数中如果想要修改外层函数的值,必须要先用nonlocal声明一下。

运行结果:
inner: 10
outer b: 20


2.LEGB规则:
local :  函数,类,方法的内部。
enclosed:  嵌套函数的外层
global:全局变量
buit in:自己保留的特殊名称。
python查找名字时:local--->enclosed---->global---->buit in.


3.类的定义:
代码:
class Student:    #类名一般首字母大写,多个单词采用驼峰命名法
    def __init__(self,name,score): #self必须位于第一个参数
        self.name = name
        self.score = score
    def say_score(self):  #self必须位于第一个参数
        print("{0}的分数是:{1}".format(self.name,self.score))
s1 = Student("小暖猫",99)
s1.say_score()


运行结果:
小暖猫的分数是:99

解释:self指的是创建的s1这个对象的地址,因此必须放在第一个位置。


4.类方法:
解释:类方法通过修饰器@classmethod来定义
格式:
@classmethod
def 类方法名(cls [,参数1,参数2]):
	函数体


注释:
1.cls指的是类对象本身。
2.调用类方法格式:类名.类方法名(参数1,参数2)
3.子类继承父类的时候,cls 是子类的对象,而不是父类的对象。

例题:
class Student:
    company = "SXT"  #类对象
    @classmethod
    def printCompany(cls):
        print(cls.company)
Student.printCompany()

运行结果:
SXT


5.静态方法:
解释:类方法通过修饰器@staticmethod来定义
格式:
@staticmethod
def 静态方法名([,参数1,参数2]):
	函数体


代码:
class Student:
    company = "SXT"  #类对象
    @staticmethod
    def add(a,b):
       print("{0}+{1}={2}".format(a,b,(a+b)))
Student.add(20,30)

运行结果:
20+30=50


6.析构函数
解释:用来删除对象,释放对象占用的资源。

代码:

class Person:
    def __del__(self):
        print("销毁对象:{0}".format(self))
p1 = Person()
p2 = Person()
del p2
print("程序结束")


运行结果:
销毁对象:<__main__.Person object at 0x010CFFD0>
程序结束
销毁对象:<__main__.Person object at 0x01185030>

解释:del p2时,销毁了p2这个对象。
当整个程序运行结束后,没有被销毁的程序都会被销毁。因此p1此时也会被销毁。


7.__call__方法和可调用对象
解释:增加这个方法,让对象可以像函数一样被调用。


代码:

class SalaryAccount:
    def __call__(self,salary):
        yearSalary = salary*12
        daySalary = salary//22.5
        hourSalary = daySalary//8

        return dict(yearSalary = yearSalary,monthSalary = salary,daySalary = daySalary,hourSalary = hourSalary)
s = SalaryAccount()
print(s(30000))  #这个地方的s的使用就是像函数一样。

运行结果:
{'yearSalary': 360000, 'monthSalary': 30000, 'daySalary': 1333.0, 'hourSalary': 166.0}


8 .python中方法没有重载(不同于java)
注意:如果方法重名了,则后面的会把前面的覆盖。


9.方法的动态性:
I:给类添加新方法。
II:修改方法。

代码:I
class Person:
    def work(self):
        print("努力上班!")

def play_game(s):
     print("{0}在玩游戏".format(s))

Person.play = play_game
p = Person()
p.work()
p.play()   #Person.play(p)


代码分析:
两个方法,只有work 方法在Person中,Person.play = play_game 这个语句实际上
相当于把play_game 方法(对象)的地址 赋值给 Person 中的 play方法(对象),这样就
相当于 Person中也存在了,play_game 方法。所以最后一句p.play()  可以运行。

运行结果:
努力上班!
<__main__.Person object at 0x02B95030>在玩游戏


代码II:
class Person:
    def work(self):
        print("努力上班!")

def play_game(s):
     print("{0}在玩游戏".format(s))

def work2(s):
    print("好好学习,挣大钱,把小暖猫娶回家!!")
    
p = Person()
Person.work = work2
p.work()

代码分析:
Person.work = work2说明:Person.work,这个方法对象的地址被work2这个方法的
地址重新赋值。所以相当于修改了Person.work这个方法。

运行结果:
好好学习,挣大钱,把小暖猫娶回家!!


10.私有属性和私有方法。
私有属性:
I:两个下划线开头的变量和方法都成为是私有的,其余的都是共有的。
II:类的内部可以直接访问,类的外部不能直接访问,可以间接访问。
III:类的外部可以通过  “_类名__私有属性(变量和方法)名”