python基础第八课

一,python中的方法没有重载
如果定义多个同名方法,则只有最后一个有效。
在其他语言中,可以通过形参列表区分但是python中不可以
测试代码如下:

class Tx:
    def prints(self):
        print('没有参数')
    def prints(self,a):
        print('参数为',a)
t=Tx()
t.prints(1)

结果如下:

参数为 1

二,方法的动态性
python是动态语言,我们可以动态的为类添加新的方法,也可以改变已有的方法

测试代码如下:

class Tips:
    def work(self):
        print('好好学习')
def play(a):
    print('{0}在玩游戏'.format(a))
def work(a):
    print('{0}在工作'.format(a))
Tips.play=play
Tips.work=work
p=Tips()
p.play() #Tips.play(p)
p.work()

结果如下:

<__main__.Tips object at 0x0000022931185B88>在玩游戏
<__main__.Tips object at 0x0000022931185B88>在工作

该代码的关键是将play与work看作对象,然后进行操作。相当于在Tips中创建一个类属性,存放函数的地址。

三,私有属性与私有方法
要点:(1)两个下划线开头的属性或方法为私有的,其他的为公共有的
(2)类内部可以直接访问私有属性和方法
(3)类外部不可以直接访问私有属性与方法
(4)在类外部可以通过_类名__私有属性名来访问私有属性
方法在本质上也是属性,只不过可以用()调用
测试代码如下:

class Employee:
    __company='yzu'
    def __init__(self,name,age):
        self.name=name
        self.__age=age   #私有属性
    def __fun(self):      #私有方法
        print('加油')
        print(Employee.__company)   #私有类属性,注意在类内部引用时,不需要加_类名,但是前面也要加类名
e=Employee('lhy',18)
print(e.name)
#print(e.age)
print(e._Employee__age)
print(dir(e))
#print(e.__fun)
print(e._Employee__fun())
print(Employee._Employee__company)

结果如下:

lhy
18
['_Employee__age', '_Employee__company', '_Employee__fun', '__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']
加油
yzu
None
yzu

四,@property修饰器
它可以将一个方法的调用变成属性调用
测试代码如下:


class Employee:
    @property
    def salary(self):
        return 10000
e=Employee()
print(e.salary)
#e.salary()错误
#e.salary=20000该方法中不可修改

结果如下:

10000

上面代码无法改变值,下面是改进代码

class Employee:
    def __init__(self,salary):
        self.__salary=salary
    def get_salary(self):
        return self.__salary
    def set_salary(self,salary):
        if 1000<salary<50000:
            self.__salary=salary
        else:
            print('输入错误')
e=Employee(3000)
print(e.get_salary())
#e.set_salary(4000)
e.set_salary(-2000)
print(e.get_salary())

#改进
class Employee:
    def __init__(self,salary):
        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('输入错误')
e=Employee(3000)
print(e.salary)
e.salary=-2000
print(e.salary)

结果如下:

3000
输入错误
3000
3000
输入错误
3000

五,面向对象三大特征
(1)封装:隐藏对象的属性和实现细节,只对外提供必要的方法
(2)继承:继承让子类具有父类的特征,提高代码重用性
(3)多态:同一种方法调用由于对象不同会产生不同的行为。

六,继承
语言格式:class 子类名(父类1,【父类2】。。。)
如果在类体中没有指定父类,则默认父类为object类,
object是所有类的父类,里面定义所有类默认实现的东西,如__new__()
一般来说,构造子类对象一般调用父类的构造函数。
对于父类的私有属性与私有方法,子类继承但不可以直接用。
测试代码如下:

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def say_age(self):
        print('年龄是{0}'.format(self.__age))


class Student(Person):       #注意缩进,unindent
     def __init__(self,name,age,score):
         Person.__init__(self,name,age)#注意要加self
         self.score=score
s=Student('lhy',18,60)
s.say_age()
print(Student.mro())#打印所属关系
#如果把age定为私有属性
print(s._Person__age)

结果如下:

年龄是18
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
18

七,类成员的继承与重写
(1)继承:子类继承父类除构造函数外的所有成员
(2)重写:子类中可以重新定义父类中的方法。
测试代码如下:

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def say_age(self):
        print('年龄是{0}'.format(self.__age))


class Student(Person):       #注意缩进,unindent
     def __init__(self,name,age,score):
         Person.__init__(self,name,age)#注意要加self
         self.score=score
     def say_age(self):
         print("{0}的年龄是{1}".format(self.name,self._Person__age))
s=Student('lhy',18,60)
s.say_age() #覆盖了父类的方法

结果为:

lhy的年龄是18

八,object根类
测试代码如下:

class Person:
    def __init__(self,name,age):
        self.name=name
        self.__age=age

    def say_age(self):
        print('年龄是{0}'.format(self.__age))
print(dir(object))
s=Person('lhy',18)
print(dir(s))
s1=s.name
s2=s._Person__age
s3=s.say_age
print(type(s1))
print(type(s2))
print(type(s3))#方法也是属性,只不过是method属性,可以用()调用

结果如下:

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
['_Person__age', '__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_age']
<class 'str'>
<class 'int'>
<class 'method'>

九,__str__方法
该方法用来返回一个对象的描述,用print()方法时,会使用该方法
测试代码如下:

class Person:
    def __init__(self,name):
        self.name=name
s=Person('lhy')
print(s)
#若使用str
class Person1:
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return '修改了' #不用return会报错
s=Person1('lhy')
print(s)

结果如下:

<__main__.Person object at 0x0000027D6CD2AD08>
修改了

十,多重继承与特殊属性
多重继承会将类的整体结构搞得复杂,应该避免使用
测试代码如下:

class A:
    def a(self):
        print('a')
    def say(self):
        print('aaa')
class B:
    def b(self):
        print('b')
    def say(self):
        print('bbb')
class C(A,B):
    pass
c=C()
c.a()
c.b()
c.say()#由于继承时候A在前面
print(C.mro())#c不可以
print(c.__dict__)
print(c.__class__)
print(C.__bases__)
print(C.__base__)
print(C.__mro__)
print(A.__subclasses__())

结果如下:

a
b
aaa
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
{}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]

十一,super()获取父类定义
在子类中,如果想获得父类方法时,可以通过super()来实现
super()代表父类的定义,不是父类的对象
测试代码如下:

class A:
    def a(self):
        print(self)
class B(A):
    def say(self):
        #A.a(self)
        super().a()#与上语句相似
        print(self)
#b=B()
#b.say()
B().say()

结果为:

<__main__.B object at 0x0000024E8A450548>
<__main__.B object at 0x0000024E8A450548>

十二,多态
多态是由于对象不同而产生不同行为
要点:(1)只有方法有多态,属性没有多态
(2)多态必须存在两个必要条件:继承与方法重写
测试代码如下:

class Man:
    def eat(self):
        print('吃饭行为')

class Chinese(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):
        m.eat()
    else:
        print('不能吃饭')

maneat(Chinese())
maneat(English())
maneat(Indian)
maneat(Man())

结果为:

用筷子吃
用刀叉吃
不能吃饭
吃饭行为

十三,特殊方法与运算符重载
测试如下:

class Person:
    def __init__(self,name):
        self.name=name
    def __add__(self, other):
        if isinstance(other,Person):#检测是不是Person类
            return "{0}__{1}".format(self.name,other.name)#这里的other其实是一个Person对象
        else:
            return "不能打印"
    def __mul__(self, other):
        if isinstance(other,int):
            return self.name*3
        else:
            return "不能打印"
p1=Person('lhy')
p2=Person('zm')
c=p1+p2
print(c)
d=p1*3
print(d)

结果为:

lhy__zm
lhylhylhy


在这里插入图片描述
十四,对象的浅拷贝与深拷贝
测试代码如下:

import copy
class Phone:
    def __init__(self,cpu,screen):
        self.cpu=cpu
        self.screen=screen
class Cpu:
    pass
class Screen:
    pass

#测试变量赋值
c=Cpu()
c2=c
print(c)
print(c2)
s=Screen()
print('测试浅拷贝')
p=Phone(c,s)#Phone(1,2)?
p1=copy.copy(p)
print(p,p.cpu,p.screen)
print(p1,p1.cpu,p1.screen)
print('测试深拷贝')
p2=copy.deepcopy(p)
print(p,p.cpu,p.screen)
print(p2,p2.cpu,p2.screen)

结果如下:

<__main__.Cpu object at 0x000001D7AFC3C748>
<__main__.Cpu object at 0x000001D7AFC3C748>
测试浅拷贝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7AFC48288> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
测试深拷贝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7B0C23248> <__main__.Cpu object at 0x000001D7B0C23BC8> <__main__.Screen object at 0x000001D7B0C23C48>

十五,组合
is-a关系用继承
has-a关系用组合
测试代码如下:

class A1:
    def a1(self):
        print('aaa')
class B1(A1):
    pass
B1().a1()

#组合
class A2:
    def a2(self):
        print('bbb')
class B2:
    def __init__(self,a):
        self.a=a
B2(A2()).a.a2()#这里B2中包含A2,然后将A2()的对象,传入B2中,用来创建a,所以a.a2()可以调用

结果如下:

aaa
bbb

十六,工厂模式实现

class CarFactory:
    def create_car(self,brand):
        if brand=='奔驰':
            return BC()
        elif brand=='比亚迪':
            return BYD()
        elif brand=='法拉利':
            return FLL()
class BC:
    pass
class BYD:
    pass
class FLL:
    pass

factory=CarFactory()
c1=factory.create_car('奔驰')
c2=factory.create_car(('比亚迪'))

十七,单例模式实现

class Dan:
    __obj=None
    init_flag=True
    def __new__(cls, *args, **kwargs):
        if cls.__obj==None:#忘加cls
            cls.__obj=object.__new__(cls)
        return cls.__obj
    def __init__(self):
        if Dan.init_flag==True:#忘加Dan
            Dan.init_flag=False
            print('执行了')

d1=Dan()
d2=Dan()
print(d1)
print(d2)

结果如下:

执行了
<__main__.Dan object at 0x0000021EB37C4B88>
<__main__.Dan object at 0x0000021EB37C4B88>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章