python学习笔记——面向对象celia2

1212-王同学

发表文章数:21

首页 » Python » 正文

方法没有重载(与其他语言不同)

定义多个重名方法,只有最后一个有效

方法的动态性

可以为类、对象添加新方法,或者修改已有的方法

class Person:

    def work(self):
        print("work hard")
 
# 创建类
p = Person()
# 调用类中的方法
p.work()


  1. 若只是调用类外部的方法是无法调用的
class Person:

    def work(self):
        print("work hard")
def play_game(s):
    print("{0}is palying games".format(s))

p = Person()
p.work()
p.play__game()

把要加的方法加到类中,这样就可以了

Person.play = play_game
p = Person()
p.work()
p.play()  # 实际上是person.play(p)
  1. 修改原方法
class Person:

    def work(self):
        print("work hard")
        
def work2(s):
    print("make money")

# 记住修改方法时新方法不用加括号
Person.work = work2
p = Person()
p.work()


私有属性

原非私有情况

class Employee():

    def __init__(self,name,age):
        # 属性
        self.name = name
        self.age = age


e = Employee("Celia",23)
print(e.name)
print(e.age)

可通过这种方法访问私有属性

class Employee():

    def __init__(self,name,age):
        # 属性
        self.name = name
        self.__age = age


e = Employee("Celia",23)
print(e.name)
print(e._Employee__age)

私有方法

  1. 调用私有方法
class Employee():
    def __work(self):
        print("work hard, make money")

e._Employee__work()
  1. 类内部用私有方法调用私有属性
class Employee():

    def __init__(self,name,age):
        # 属性
        self.name = name
        self.__age = age

    def __work(self):
        print("work hard, make money")
        print("age{0}".format(self.__age))

e._Employee__work()
class Employee():

    # 类的私有类对象
    __company = "Celia"
    def __work(self):
        print(Employee.__company)

# 在类外部调用私有类对象
print(Employee._Employee__company)

@property装饰器

作用:将一个方法的调用变成属性的调用,用来增加get、set方法

举例

  1. 简单示例
    传统调用:
class Employee:

    def salary(self):
        return 10000

emp1 = Employee()
emp2.salary()

用@property

class Employee:

    @property
    def salary(self):
        return 10000

emp1 = Employee()
print(emp1.salary)

# 不能设置方法
# emp1.salary = 20000
  1. 调用私有属性——最好把类中的属性设为私有,否则容易出错。然后利用get和set对参数的取值进行约束,以防顾客输入不可行数值时无法纠正

一般方法调用私有属性:

class Employee:

    def __init__(self,name,salary):
        self.__name = name
        self.__salary = salary

    def get_salary(self):
        return self.__salary

    def set_salary(self,salary):
        if 1000 < salary < 500000:
            self.__salary = salary
        else:
            print('wrong data! The number should be in 1000-50000')



emp1 = Employee("Celia", 20000)
print(emp1.get_salary())
emp1.set_salary(2000)  # 输入2000
print(emp1.get_salary())

若用@property就不用加get和set方法了。也简化了调用

class Employee:

    def __init__(self, name, salary):
        self.__name = name
        self.__salary = salary

    @property
    def salary(self):  # 代替了get salary
        return self.__salary

    @salary.setter  # 再加上一个装饰器,表示针对salary属性的一个设置
    def salary(self, salary):  # 代替了set salary
        if 1000 < salary < 500000:
            self.__salary = salary
        else:
            print('wrong data! The number should be in 1000-50000')


emp1 = Employee("Celia",30000)
print(emp1.salary)  # 读取
emp1.salary = 2000  # 赋值
print(emp1.salary)
# 输出结果
30000
2000

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

封装:将细节封装,只留下调用和赋值供用户使用(调用界面越简单越好)。

继承: 一个子类可以有多个直接的父类
python学习笔记——面向对象celia2
继承举例:

  1. 虽然Student类当中什么也没有,但是继承自Person类的方法。可以调用
# 继承
# 定义一个Person类
class Person:
    def say_age(self):
        print("age, I don't know")


# Student类继承Person类
class Student(Person):
    pass


# Student-->Person-->object类(最原始类)
print(Student.mro())

s = Student()
s.say_age()
  1. 调用父类初始化方法(必须显式调用父类初始化方法,否则解释器不会调用)
    ①查询子类是否包含了父类的内容
    私有的方法和属性属性子类继承了,但是不可以随便调用
    如何调用父类的私有属性及方法
class Person:

    def __init__(self,name,age):
        self.name = name
        self.__age = age  # 看看私有属性能否调用

    def say_age(self):
        print("age, I don't know")


# Student类继承Person类
class Student(Person):

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



# Student-->Person-->object类(最原始类)
print(Student.mro())

s = Student("Celia", 23,100)
s.say_age()
print(s.name)  # 查询子类是否包含了父类的内容
print(s.age)  # 私有的方法属性子类继承了,但是不可以随便调用
print(dir(s))  # 可用此方法看看子类是否真的继承了父类的方法
print(s._Person__age)  # 可以这样调用私有属性

测试方法的重写(常用)

原方法:

class Person:

    def __init__(self,name,age):
        self.name = name
        self.__age = age  # 私有属性

    def say_age(self):
        print("age:", self.__age)

    def say_introtuce(self):
        print("my name:{0}".format(self.name))

class Student(Person):
    # 与原父类方法相同
    def __init__(self,name,age,score):
        Person.__init__(self,name,age)
        self.score = score

s = Student("Celia",18,90)
s.say_age()
s.say_introtuce()

**重写方法"say_introduce":**在调用子类创建对象时,子类重写的方法可以覆盖父类的方法

class Person:

    def __init__(self,name,age):
        self.name = name
        self.__age = age  # 私有属性

    def say_age(self):
        print("age:", self.__age)

    def say_introtuce(self):
        '''重写了父类的方法'''
        print("Teacher! my name is:{0}".format(self.name))

class Student(Person):

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

s = Student("Celia",18,90)
s.say_age()
s.say_introtuce()

查看类的继承层次结构

通过类的方法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'>]
# C继承自B-A-Obgect

dir()内置函数

可查看属性

object根类

是所有类的父类

class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_age(self):
        print(self.name, "的年龄是:", self.age)


obj = object()
print(dir(obj))

s2 = Person("celia", 23)
print(dir(s2))
['__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__']

['__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']

重写obgect的__str__()

class Person:  # 默认继承obgect类

    def __init__(self, name):
        self.name = name

    # 重写
    def __str__(self):
        return "name is :{0}".format(self.name)


p = Person("celia")
print(p)

多重继承(子类可以具备多个父类的特点)

一般情况尽量避免使用,方式结构过于复杂易造成网状结构

super()获取父类的定义(可以将定义看作是代码)

在子类中,如果想要获取父类的方法,可以用super()来做
注意:不是获取父类的对象
练习:测试super()
首先,我们可以这样做:

class A:

    def say(self):
        print("A", self)


class B:

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

B().say()

或者用super()

class A:

    def say(self):
        print("A", self)


class B:

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

B().say()

多态

  • 由于对象的不同,产生不同的行为
  • 多态是方法的多态,不是属性的
  • 两个必要条件:继承、方法的重写
class Man:
    def eat(self):
        print("hungry and eat")

class Chinese(Man):
    def eat(self):
        print("chinese eating")

class English(Man):
    def eat(self):
        print("English eating")

class Indian(Man):
    def eat(self):
        print("using hand")

def maneat(m):
    if isinstance(m,Man):  # m如果是Man的子类的话,调用方法
        m.eat()
    else:
        print("cannot eat")


maneat(Chinese())
maneat(English())

特殊方法和运算符重载

使自定义的类生成的对象能够使用运算符进行操作
python学习笔记——面向对象celia2
运算符函数需要什么去网上搜
python学习笔记——面向对象celia2

这里以加法、乘法为例进行运算符重载举例

class Person:
    def __init__(self,name):
        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("Celia")
p2 = Person("lucy")

x = p1+p2
print(x)

y = p1*p2
print(y)

Z = p1*3
print(Z)
Celia--lucy
不能相乘
CeliaCeliaCelia

特殊属性

python学习笔记——面向对象celia2

对象的浅拷贝与深拷贝

浅复制

import copy


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

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

class Screen:
    def show(self):
        print("显示一个好看的画面")
        print("screen对象:",self)


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

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

# 打印不同对象(手机)及其下的cpu,screen看看是否相同
print(m1, m1.cpu, m1.screen)
print(m2, m2.cpu, m2.screen)

发现对象不同,但是cpu和screen都一样,但只复制了对象本身,没有其”子子孙孙“

<__main__.CPU object at 0x00000198D22AEB70>

<__main__.CPU object at 0x00000198D22AEB70>

<__main__.MobilePhone object at 0x00000198D22AEF28> <__main__.CPU object at 0x00000198D22AEB70> <__main__.Screen object at 0x00000198D22AEEF0>

<__main__.MobilePhone object at 0x00000198D22AFB38> <__main__.CPU object at 0x00000198D22AEB70> <__main__.Screen object at 0x00000198D22AEEF0>

深复制

import copy


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

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

class Screen:
    def show(self):
        print("显示一个好看的画面")
        print("screen对象:",self)


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

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

# 打印不同对象(手机)及其下的cpu,screen看看是否相同
print(m1, m1.cpu, m1.screen)
print(m2, m2.cpu, m2.screen)

# 测试深复制
print("测试深复制")
m3 = copy.deepcopy(m1)
print(m1, m1.cpu, m1.screen)
print(m3, m3.cpu, m3.screen)

输出的cpu和screen都是与m1不同的

测试深复制
<__main__.MobilePhone object at 0x00000233D609EEF0> <__main__.CPU object at 0x00000233D609EB70> <__main__.Screen object at 0x00000233D609EF28>
<__main__.MobilePhone object at 0x00000233D6095B00> <__main__.CPU object at 0x00000233D89B9A90> <__main__.Screen object at 0x00000233D89B9F60>

组合

“has a”关系是组合:手机由cpu
“is a”关系是继承:狗是一个动物

# 测试组合

class A1:

    def say_a1(self):
        print("yes ok")

# 用组合:把A1的对象作为自己的属性
class A2:
    def __init__(self,a):
        self.a = a

a1 = A1()
a2 = A2(a1)
a2.a.say_a1()

设计模式——工厂模式

class CarFactory:

    def create_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.create_car("奔驰")
print(c1)
c2 = factory.create_car("比亚迪")
print(c2)
<__main__.Benz object at 0x000001FC842DEEF0>
<__main__.BYD object at 0x000001FC842DFB38>

设计模式——单例模式

  • 确保一个类只有一个实例(对象),减少系统的开销
  • 通常需要重写new方法,和构造器构造方法
class MySingleton:

    __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 MySingleton.__init_flag:
            print("init……")
            self.name = name
            MySingleton.__init_flag = False

a = MySingleton("aa")
b = MySingleton("bb")
print(a)
print(b)
c = MySingleton("cc")
print(c)

拜师教育学员文章:作者:1212-王同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《python学习笔记——面向对象celia2》 发布于2020-09-11

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录