Python_day08_面向对象

方法没有重载

Python中,方法的参数没有参数类型(调用时确定参数的类型),参数的数量也可以由可变参数控制。因此Python中是没有方法的重载的。定义一个方法即可有多种调用方式,相当于实现了其他语言中的方法的重载。
如果我们在类中定义了多个重名的方法,只有最后一个方法有效。
建议不要用重名的方法,Python中方法没有重载。

# Python中没有方法的重载。定义多个同名方法,只有最后一个有效。
class Person:
    def say_hi(self):
        print('hi')
    def say_hi(self,name): # 此时就会将上面的say_hi()函数覆盖
        print('hi',name)

p1 = Person()

方法的动态性

Python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。

class Person:
    def work(self):
        print('努力上班!')

def play_game(s):
    print(s,'在玩游戏')
def work2(s):
    print('好好工作,努力上班!')

Person.play = play_game
p = Person()
p.work() # 努力上班!
# 相当于 Person.play(p)
p.play() # <__main__.Person object at 0x10d137c10> 在玩游戏
print('-----')
Person.work = work2
p.work() # 好好工作,努力上班!

私有属性和私有属性(实现封装)

class Employee:

    __company = 'HUAWEI'

    def __init__(self,name,age):
        self.name = name
        self.__age = age # 私有属性
    def __work(self): # 私有方法
        print('好好工作')
        print('年龄:',self.__age) # 在类内部调用自己私有的属性
        print(Employee.__company) #类内部调用私有的类变量

e = Employee('GSH',12)
print(e.name)
# print(e.age) # 因为age现在是私有属性 访问不到
print(e._Employee__age) # 现在就可以访问到了 前提是你得知道这个属性 所以才能通过此方式访问
print(dir(e))
# e.work() # 因为work方法现在是私有方法 这种调用方法调用不到
e._Employee__work() # 访问私有方法的方法
print(Employee._Employee__company)

输出:

GSH
12
['_Employee__age', '_Employee__company', '_Employee__work', '__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']
好好工作
年龄: 12
HUAWEI
HUAWEI

@property 装饰器 装饰器写get()set()方法

可以将一个方法调用方式变成’属性调用’。

# @property装饰器用法
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('录入错误 请输入1000-500000之间的薪资')

'''
    def get_salary(self): # 原始的get和set方法
        return self.__salary
    def set_salary(self,salary):
        if 1000 < salary <50000:
            self.__salary = salary
        else:
            print('录入错误 请输入1000-500000之间的薪资')
'''
emp1 = Employee("GSH",30000)
# print(emp1.get_salary())
# emp1.set_salary(20000) # 录不进去
# print(emp1.get_salary())

# 使用装饰器后 直接使用 对象.方法名 就可以了
print(emp1.salary) # 30000
emp1.salary = 2000
print(emp1.salary) # 2000

面向对象的三大特征说明(封装、继承、多态)

Python是面向对象的语言,也支持面向对象的三大特性: 继承 封装(隐藏) 多态

  • 封装: 通过前面的私有属性 和 私有方法的方式 实现封装
  • 继承: 继承可以让子类具有父类的特性 提高代码的重用性
  • 多态: 多态是指同一个方法调用由于想象力不同会产生那个的行为

继承

继承是面向对象程序设计的重特征,也是实现**‘代码复用’**的重要手段
如果一个新类继承自一个设计好的类,就直接具备了已有类的特征。
语法格式:
Python支持多重继承,一个子类可以继承多个父类。

class 子类类名(父类[,父类2,...]):
		类体

如果类定义没有指定父类,则默认父类是Object类。object是所有类的父类,里面定义了一些所有类共有的默认实现。
比如: __init__(self,参数列表)
例子:

# 继承的基本使用

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age #私有属性
    def say_age(self):
        print(self.name,'的年龄是',self.__age)

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

# [<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
# print(Student.mro())

s1 = Student('GSH',23,89)
s1.say_age() # 此时我们可以调用父类内的方法
print(s1.name)
print('-----')
print(dir(s1))

输出:

/Applications/Anaconda-Navigator.app/Contents/MacOS/python /Users/guosihan/PycharmProjects/MyTest/day_8/Object_test6.py
GSH 的年龄是 23
GSH
-----
['_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', 'score']

Process finished with exit code 0
类成员的继承和重写
  1. 成员继承: 子类继承了父类除构造函数之外所有的成员。
  2. 方法重写: 子类可以重新定义父类的方法,这样就会覆盖父类的方法,称为重写。
class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age #私有属性
    def say_age(self):
        print(self.name,'的年龄是',self.__age)
    def say_introduce(self):
        print('我的名字是{0}'.format(self.name))

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

s1 = Student('张三',24,90)
s1.say_introduce() # 输出: 报告老师 我的名字是: 张三
查看具体类的继承层次结构

通过类的方法mro()或者类的属性__mro__可以输出这个类的继承层次结构。

dir()查看对象属性

上面代码有说明

重新__str__方法

object有一个__str__方法,用于返回一个对于’对象的描述’,对应内置函数str(),经常用于print()方法,帮我我们查看对象的信息。
在这里我们重写__str__方法。

class Person: # 默认继承Object类
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return '名字是:{0}'.format(self.name)

p = Person('GSH')
print(p) # 名字是:GSH 这是对对象的描述 用print()方法可以将函数内__str__()方法内的字符串输出出来
多重继承
class A:
    def aa(self):
        print('aa')
class B:
    def bb(self):
        print('bb')
class C(A,B):
    def cc(self):
        print('cc')

c = C()
c.aa() # aa
c.bb() # bb
c.cc() # cc
MRO() 查看继承类
class A:
    def aa(self):
        print('aa')
    def say(self):
        print('say AA')
class B:
    def bb(self):
        print('bb')
    def say(self):
        print('say BB')
class C(A,B):
    def cc(self):
        print('cc')

c = C()
c.aa()
c.bb()
c.cc()
print(C.mro()) # 打印类的层次结构
c.say() # 解释器寻求的方式是'从左到右'的方式寻找 此时输出的A中的say()方法

输出:

aa
bb
cc
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
say AA
super()获取父类的定义
class A:
    def say(self):
        print('A',self)

class B(A):
    def say(self):
        A.say(self) # 调用父类A类的方法
        print('B',self)
        super().say() # 同样调用父类A类的方法

B().say()

输出:

A <__main__.B object at 0x105582d50>
B <__main__.B object at 0x105582d50>
A <__main__.B object at 0x105582d50>

多态

是指同样一个方法调用由于对象不同可能会产生不同的行为。

多态:

  1. 多态是方法的多态,属性并没有多态。
  2. 多态的存在有2个必要条件: 继承 方法的重写。
class Man:
    def eat(self):
        print('要吃饭')
class Chinese(Man):
    def eat(self):
        print('筷子')
class Englist(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(Englist()) # 刀叉
manEat(Indian())  # 右手
# 他们都继承自Man类 有同样的方法 但是方法内部执行语句不同
特殊方法和运算重载
# 测试运算符的重载
class Person:
    def __init__(self,name,age):
        self.name = name
    def __add__(self, other):
        if isinstance(other,Person):
            return '{0} -- {1}'.format(self.name,other.name)
        else:
            return '不是同类对象,不能相加'
    def __mul__(self, other):
        if isinstance(other,int):
            return self.name * other
        else:
            return '不是同类对象,不能相乘'

p1 = Person('GSH',33)
p2 = Person('RTY',54)

x = p1 + p2 # 将 + 进行重写
print(x)

print(p1 * 6)

输出:

GSH -- RTY
GSHGSHGSHGSHGSHGSH
特殊属性

Python对象中包含了很多双下划线开始和结束的属性,这就是特殊属性,有特殊用法。

# 测试一些特殊属性
class A:
    def aa(self):
        print('aa')
    def say(self):
        print('say AA')
class B:
    def bb(self):
        print('bb')
    def say(self):
        print('say BB')
class C(A,B):
    def __init__(self,nn):
        self.nn = nn
    def cc(self):
        print('cc')

c = C(21)
c.aa()
c.bb()
c.cc()
print('-----1-----')
print(C.mro())
c.say()
print('-----2-----')
print(dir(c))
print('-----3-----')
print(c.__dict__)
print('-----4-----')
print(c.__class__)
print('-----4-----')
print(C.__bases__)
print(C.__mro__)
print('-----5-----')
print(A.__subclasses__())

输出:

aa
bb
cc
-----1-----
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
say AA
-----2-----
['__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__', 'aa', 'bb', 'cc', 'nn', 'say']
-----3-----
{'nn': 21}
-----4-----
<class '__main__.C'>
-----4-----
(<class '__main__.A'>, <class '__main__.B'>)
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
-----5-----
[<class '__main__.C'>]

在这里插入图片描述

对象的浅拷贝和深拷贝

  • 变量的赋值操作: 只是形成两个变量 实际上指的是同一个对象
  • 浅拷贝: Python拷贝一般都是浅拷贝。拷贝时,对象包含的子对象内容不拷贝,因此,源对象和拷贝的对象引用同一个子对象
  • 深拷贝: 使用Copy模块的deepcopy函数 递归函数拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象不同
import copy
# 测试对象的浅拷贝和深拷贝

class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen

class CPU:
    def calculate(self):
        print('计算中')
        print('cpu为:',self)

class Screen:
    def show(self):
        print('1080p')
        print('screen对象:',self)

# 测试变量赋值
print('测试变量赋值')
c1 = CPU()
c2 = c1
print(c1)
print(c2)

# 测试浅拷贝
print('测试浅赋值')
s1 = Screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)
print(m1,m1.cpu,m2.screen) # 第一个元素不一样 后面两个元素是一样的
print(m2,m2.cpu,m2.screen)

# 测试深赋值 子对象全部重新赋值
print('测试深赋值')
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m2.screen) # 全都不一样
print(m3,m3.cpu,m3.screen) # 全都不一样

输出:

测试变量赋值
<__main__.CPU object at 0x102f17310>
<__main__.CPU object at 0x102f17310>
测试浅赋值
<__main__.MobilePhone object at 0x102f20250> <__main__.CPU object at 0x102f17310> <__main__.Screen object at 0x102f20190>
<__main__.MobilePhone object at 0x102f202d0> <__main__.CPU object at 0x102f17310> <__main__.Screen object at 0x102f20190>
测试深赋值
<__main__.MobilePhone object at 0x102f20250> <__main__.CPU object at 0x102f17310> <__main__.Screen object at 0x102f20190>
<__main__.MobilePhone object at 0x102f20fd0> <__main__.CPU object at 0x102f2a150> <__main__.Screen object at 0x102f2a1d0>

组合

is - a – 继承 – 从而实现子类拥有父类的方法和属性 – dog is a animal 。狗类就应该继承动物类
has - a – 组合 – 也可以实现一个类拥有另一个类的方法和属性 – Mobile has a CPU。手机拥有CPU
区别:

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: guosihan
@file: Object_test15.py
@time: 2020/04/03
@desc:
"""
# 继承
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) # 此时B就拥有了A B(self).a也就可以调用say_a2()方法
b2.a.say_a2()

输出:

a1 a1 a1
a2 a2 a2

类的组合的单独的例子:

#类的组合的例子:
class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen

class CPU:
    def calculate(self):
        print('计算中')
        print('cpu为:',self)

class Screen:
    def show(self):
        print('1080p')
        print('screen对象:',self)

m = MobilePhone(CPU(),Screen()) #MobilePhone拥有了CPU()和Screen() 所以m.cpu就可以调用calculate()方法
m.cpu.calculate() #MobilePhone拥有了CPU()和Screen() 所以m.screen就可以调用show()方法
m.screen.show()

输出结果:

计算中
cpu为: <__main__.CPU object at 0x10869cf90>
1080p
screen对象: <__main__.Screen object at 0x1086a1090>

设计模式_工厂模式实现

设计模式是面向对象语言特有的内容,是我们在面临某一类问题时候固定的做法,设计模式有很多种,比较流行的有: GOF等23种设计模式
设计模式分为 工厂模式和单例模式
工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类,创建对象进行统一的管理和控制

# 测试工厂模式
# GOF(Group Of Four)
class CarFactory:
    def creat_car(self,brand):
        if brand == '奔驰':
            return Benz()
        elif brand == '宝马':
            return BMW()
        elif brand == '比亚迪':
            return BYD()
        else:
            return '未知品牌'

class Benz:
    pass

class BMW:
    pass

class BYD:
    pass

# 创建对象
factory = CarFactory()
c1 = factory.creat_car('奔驰')
c2 = factory.creat_car('比亚迪')
print(c1)
print(c2)

输出结果:

<__main__.Benz object at 0x108c8af90>
<__main__.BYD object at 0x108c8afd0>

设计模式_单例模式实现

单例模式的核心作用是一个确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。

# 单例模式
class MySingleleton:
    __obj = None # 类属性
    __init__flag = True
    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj
    def __init__(self,name):
        if MySingleleton.__init__flag:
            print('__init__is running')
            self.name = name
            MySingleleton.__init__flag =  False

a = MySingleleton('aa')
b = MySingleleton('bb')
print(a)
print(b)
c = MySingleleton('cc')
print(c)

输出结果:

__init__is running
<__main__.MySingleleton object at 0x1065aaf10>
<__main__.MySingleleton object at 0x1065aaf10>
<__main__.MySingleleton object at 0x1065aaf10>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值