1.@property 修饰器
作用:将一个方法的调用方式变成属性的调用。

代码1::
class Employee:

    def salary(self):
        print("salary run ...")
        return 10000
emp1 = Employee()
emp1.salary()

运行结果:

salary run ...

代码2:

class Employee:

    @property
    def salary(self):
        print("salary run ...")
        return 10000
emp1 = Employee()
print(emp1.salary)

运行结果:

salary run ...
10000


两个代码的分析:第一个就是普通的方法的的调用,它不会打印出返回值,但是能够
打印出print语句来。第二种在方法前加上 @property,最后的print(emp1.salary),
直接像调用emp1的属性那样,可以直接打印出属性的返回值10000。

代码3:
class Employee:
    def __init__(self,name,salary):
        self.__name = name   #私有变量,外部无法直接访问
        self.__salary = salary

    def get_salary(self): #只能用get  set 方法间接返回
        return self.__salary  
    def set_salary(self,salary):
        if 1000<salary<50000:
            self.__salary = salary
        else:
            print("输入错误!")
emp1 = Employee("任善文",30000)  #第一次传入30000
print(emp1.get_salary())   #此时打印出的应该是30000
emp1.set_salary(2000)      #调用set方法,修改salary
print(emp1.get_salary())   #此时打印的应该是修改后的2000

运行结果:
30000
2000

将2000改成-2000运行结果:
30000
输入错误!
30000


代码4:

class Employee:
    def __init__(self,name,salary):
        self.__name = name   #私有变量,外部无法直接访问
        self.__salary = salary
    @property   #修饰器
    def salary(self):
        return self.__salary
    @salary.setter
    def salary(self,salary):
        if 1000<salary<50000:
            self.__salary = salary
        else:
            print("录入错误!!!")

emp1 = Employee("任善文",30000)  #第一次传入30000
print(emp1.salary)  #直接像属性那样直接调用
emp1.salary = -2000
print(emp1.salary)


运行结果:

30000
录入错误!!!
30000



2.面向对象———继承。
解释:子类继承父类,除了构造方法之外的所有成员。
代码:
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        #self.__age = age   如果改成私有的,则子类会继承,但是子类不能用
    def say_age(self):
        print("年龄,年龄,我也不知道")

class Student(Person): #Student继承了Person
    def __init__(self,name,age,score):  #自己的新的方法。
        Person.__init__(self,name,age)   #必须显示的调用父类的初始化方法,不然解释器不会调用
        self.score = score

print(Student.mro())   #打印出Student的继承状态

s = Student("任善文",10,30)  #给Student类传入三个值
s.say_age()  #调用继承的父类的方法
print(s.name)  #打印父类的变量
#print(s.age)
print(dir(s))   #这个函数会打印出对象的全部属性。


运行结果:
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
年龄,年龄,我也不知道
任善文
['__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__', 'age', 'name', 'say_age', 'score']



3.方法的重写:
解释:子类修改继承的父类的方法。
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        #self.__age = age   如果改成私有的,则子类会继承,但是子类不能用
    def say_age(self):
        print("我的年龄:",self.age)
    def say_introduce(self):
        print("我的名字是:".format(self.name))

class Student(Person): #Student继承了Person
    def __init__(self,name,age,score):  #自己的新的方法。
        Person.__init__(self,name,age)   #必须显示的调用父类的初始化方法,不然解释器不会调用
        self.score = score
    def say_introduce(self):  #重写父类的方法。
        print("报告老师,我的名字是:{0}".format(self.name))

s = Student("任善文",22,99)
s.say_age()
s.say_introduce()  #调用的是修改后的方法。



运行结果:
我的年龄: 22
报告老师,我的名字是:任善文

4.object根类
通过类的方法mro()或者__mro__可以输出这个类的继承层次结构。
代码:
class A:
    pass
class B(A):
    pass
class C(B):
    pass
print(C.mro())

运行结果:

[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]


5.重写 __str__()方法:
解释:object的一个方法,用来查看对象的信息,__str__()可以重写。
代码1:
class Person:
    def __init__(self,name):
        self.name = name
p = Person("任善文")
print(p)
运行结果:
<__main__.Person object at 0x02C30E70>

此时打印的是P这个对象的基本信息。

代码2:
class Person:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return "名字是:{0}".format(self.name)
p = Person("任善文")
print(p)

运行结果:
名字是:任善文
解析:由于加上了__str__()这个方法,重写了Person的构造方法 __init__()
所以再次打印的时候,会调用下面的这个方法。


6.多重继承(与java不同)
解释:一个子类有多个直接的父类。
代码:

class A:
    def aa(self):
        print("aa")
class B:
    def bb(self):
        print("bb")
class C(B,A):
    def cc(self):
        print("cc")

c = C()
c.cc()
c.bb()
c.aa()


运行结果:
cc
bb
aa

7.mro()函数
解释:Python支持多继承,如果父类中有相同的名字的方法,在子类没有
指明父类名时,解释器将“从左到右的顺序检索”
MRO:方法解析顺序。我们可以通过mro()方法获得类的层次结构。
代码:
class A:
    def aa(self):
        print("aa")
    def say(self):
        print("say AAA!")
class B:
    def bb(self):
        print("bb")
    def say(self):
        print("say BBB!")
class C(B,A):
    def cc(self):
        print("cc")

c = C()
print(C.mro()) #打印出类的层次结构
c.say()  #会执行B中的say方法

运行结果:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
say BBB!


解释:如果将C(B,A)换成C(A,B),那么就会先调用A的方法。


7.super()获取父类的

代码1:
class A :
    def say(self):
        print("A:",self)


class B:
    def say(self):
        A.say(self)
        print("B:",self)

B().say()

运行结果:

A: <__main__.B object at 0x00DDFFD0>
B: <__main__.B object at 0x00DDFFD0>

解释:说明A B 两个方法都被调用了。

8.多肽
解释:1.多肽是方法的多肽,属性没有多肽。
          2.多肽的必要条件是  继承和重写。
代码:
#  多肽
class Man:
    def eat(self):
        print("饿了,吃饭了!")
class Chinese(Man):#继承了Man
    def eat(self):
        print("中国人用筷子吃饭!")
class English(Man):
    def eat(self):
        print("英国人用叉子吃饭!")
class Indian(Man):
    def eat(self):
        print("印度人用右手吃饭")

def manEat(m): #定义一个方法
    if isinstance(m,Man):  #isinstance 是python的内置函数,用来判断对象的变量类型,也就是说,如果m是man类型就执行这句话
        m.eat()   #多肽,一个方法的调用,根据对象的不同,结果不同。
    else:
        print("不能吃饭!")

manEat(Chinese())
manEat(English())

运行结果:
中国人用筷子吃饭!
英国人用叉子吃饭!

9.对象的浅拷贝和深拷贝:
解释:浅拷贝 拷贝时,只拷贝本身。
深拷贝:递归的拷贝子对象。
# 测试对象的浅拷贝和深拷贝

代码:
import copy  #导入copy 模块
class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen

class CPU:
    def calculate(self):
        print("算你个12345")
        print("cup对象",self)

class Screen:
    def show(self):
        print("显示一个好看的画面。亮瞎你的钛合金大眼")
        print("screen对象",self)

#测试变量的赋值
c1 = CPU()
c2 = c1
print(c1)
print(c2)  #这里我们可以知道c1和c2引用是相同的

#测试浅复制
print("测试浅复制")
s1 = Screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)

print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen)#这里我们可以得出,MobilePhone地址改变但是cpu和screen的地址没有改变

#测试深复制
print("测试深复制")
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen)#我们会发现全部改变了,也就是递归到上层了


运行结果:
<__main__.CPU object at 0x02C5EAF0>
<__main__.CPU object at 0x02C5EAF0>
测试浅复制
<__main__.MobilePhone object at 0x02C5EB70> <__main__.CPU object at 0x02C5EAF0> <__main__.Screen object at 0x02C5EF50>
<__main__.MobilePhone object at 0x02C73510> <__main__.CPU object at 0x02C5EAF0> <__main__.Screen object at 0x02C5EF50>
测试深复制
<__main__.MobilePhone object at 0x02C5EB70> <__main__.CPU object at 0x02C5EAF0> <__main__.Screen object at 0x02C5EF50>
<__main__.MobilePhone object at 0x02CF0BD0> <__main__.CPU object at 0x02CF0CB0> <__main__.Screen object at 0x02CF0CF0>


10.组合:
继承和组合的区别:
“is--a”:狗是动物,狗继承动物
"has--a":手机拥有CPU ,CPU组合成手机
#用继承实现代码的复用
class A1:
    def say_a1(self):
        print("a1,a1,a1")

class B1(A1):
    pass

b1 = B1()
b1.say_a1()

#用组合实现代码的复用
代码:

class A2:
    def say_a2(self):
        print("a2,a2,a2")
class B2:
    def __init__(self,a):
        self.a = a

a2 = A2()
b2 = B2(a2)  #b2是由a2组合而成
b2.a.say_a2() #b2的变量a可以调用A2中的方法 say_a2


运行结果:
a1,a1,a1
a2,a2,a2