阶段1_Python基础06_面向对象编程

Summary

面向对象编程(概念,构造函数 __init__()[创建实例对象并将其初始化],实例对象,实例属性,实例方法,类属性,类方法,静态方法<4>,__del__析构方法,__call__()方法<5>,方法没有重载<6>,方法的动态性<7>,面向对象的三大特征[封装,继承,多态]<8>,私有属性和私有方法(封装)<9>,@property装饰器(get方法),set方法<10>,继承<11>,多重继承<11>,方法重写<12>,查看继承层次结构<12><14>,重写__str__()方法<13>,super()获得父类的定义<15>,多态<16>,特殊方法和特殊属性<17>,变量赋值<18>,对象的浅拷贝和深拷贝<18>,组合<18>,单例模式和工厂模式<19>)

Questions

1.Python支持哪三种编程方式?

2.面向对象(object oriented)和面向过程(procedure oriented)的适用范围是什么?

3.什么是对象?什么是类?类和对象是什么关系?

4.给定以下代码

代码1

class student:
    def __init__(self, name, score):    #初始化创建的对象
        self.name = name    #实例属性,初始化指的是给实例属性赋值
        self.score = score	#实例属性从属于实例对象的属性

    def say_score(self):
        print("{0}的分数是:{1}".format(self.name, self.score))

s1 = student("santa", 99)    #通过类名()调用构造函数
s1.say_score()

s1.age = 25    #可以通过obj.实例属性名的方法添加新属性
s1.salary = 99000
print("santa的薪资是{0}".format(s1.salary))

s2 = student("nanako", 97)
s2.say_score()

class man:
    pass	#空语句

print(dir(s2))    #获得对象的所有属性和方法
print(s2.__dict__)    #获得对象的属性字典
print(isinstance(s2, man))    #判断s2是否属于类对象man

输出结果

santa的分数是:99
santa的薪资是99000
nanako的分数是:97
['__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_score', 'score']
{'name': 'nanako', 'score': 97}
False

(1)Python对象有哪些组成部分;(2)__new__()和 __init__()代表什么?(3)构造函数的写法是什么?通常起到什么作用?有没有返回值?构造函数第一个参数是什么?有什么含义?如何调用构造函数?(4)示例属性如何定义?在其他实例方法中,如何访问实例属性?如何通过实例对象访问实例属性?(5)实例方法的定义和格式是什么?需要给self传参吗?上述代码中s1.say_score()在解释器中是怎样翻译的?

代码2

class student:
    company = "santates.corp"    #类属性
    count = 0   #类属性

    def __init__(self, name, score):
        self.name = name    #实例属性
        self.score = score    #实例属性
        student.count = student.count + 1

    def say_score(self):    #实例方法
        print('我的公司是:', student.company)
        print(self.name, '的分数是:', self.score)

s1 = student("santa", 99)
s1.say_score()
print('一共创建{0}个对象'.format(student.count))

(6)什么时候会创建类对象?类属性是从属于什么的属性?可以被实例对象共享吗?类属性的定义方式是什么?通过什么格式来读写?分析上面的代码,画出内存分析图,标注出类属性

代码3

class student:
    company = "santates.corp"
    def __init__(self, name, score):
        self.name = name
        self.score = score
    @classmethod
    def printCompany(cls):
        print(cls.company)

student.printCompany()
s1 = student('santa', 99)
s1.printCompany()

输出结果

santates.corp
santates.corp

(7)类方法从属于什么?定义的格式是什么?调用类方法的格式是什么?类方法中访问实例属性和实例方法会怎么样?

代码4

class student2:
    def __init__(self, name, score):
        self.name = name
        self.score = score
    @staticmethod
    def add(a, b):
        print('{0} + {1} = {2}'.format(a, b, a + b))

s2 = student2("nanako", 97)
s2.add(10, 30)

(8)静态方法与普通函数的区别在哪里?格式是什么?静态方法中访问实例属性和实例方法会怎么样?

5.分析下列代码并回答问题

代码1

class person:
    def __del__(self):
        print('销毁对象:{0}'.format(self))

p1 = person()
p2 = person()
del p2
print('程序结束')

(1)说出代码的输出结果;(2)对象在什么情况下,垃圾回收器会调用__del__方法;(3)可以使用什么语句删除对象,保证调用__del__方法;

代码2

class salary_accout:
    def __call__(self, salary):
        print("计算工资")
        year_salary = salary * 12
        return print(year_salary)
s = salary_accout()
s(10000)

(4)说出代码的执行结果?并说明什么是可调用对象?
6.如果定义了多个重名的方法,在python中会怎样?

7.说出下列代码的输出结果

class test:
    def test1(self):
        print("aaa")

def test2(s):
    print("bbb")

def test3(s):
    print('ccc')

test.extra = test2
test.test1 = test3
a = test()
#编译器的翻译:test.extra(a),相当于test2(a)
a.extra()
#可以修改原有的方法
a.test1()

8.简要地叙述面向对象三大特征的概念

9.按照要求改写代码

(1)

代码1

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

e = employee('santa', 18)
print(e.name)
print(e.age)

输出结果

santa
18

将代码1中employee方法的age属性改为私有属性并访问

回答问题:通常两个下划线开头的属性是()的,其他是()的;类内部[可以/不可以]访问私有属性;类外部[可以/不可以]直接访问私有属性/方法,可以通过()访问私有属性/方法;方法本质上也是()

(2)

代码2

class employee:
    company = 'santates.corp'
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def work(self):
        print("aaa")
e = employee('santa', 18)
e.work()
print(e.company)

输出结果

aaa
santates.corp

将上面代码中的类方法和work方法改为私有方法并访问

10.按照要求改写下面的代码

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 salary >= 0:
            self.__salary = salary
        else:
            print("录入错误")

s1 = employee('santa', 10000)
print(s1.get_salary())
s1.set_salary(20000)
print(s1.get_salary())
s1.set_salary(-100)

输出结果

10000
20000
录入错误

使用@property和@salary.setter方法改写上面的代码

11.按照要求写代码

(1)给定如下代码:

class person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def say_score:
        print("I don't know")

设定一个子类student,将person作为父类,并得到以下的结果

输出结果

I don't know
santa
25
['__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__', '_person__age', 'name', 'say_score', 'score']

回答以下问题:python是否支持多重继承,语法格式是什么?如果没有指定父类,默认父类是什么?定义子类时,需要在构造函数中调用父类的构造函数,格式是什么?

(2)多重继承:说出下列代码的结果(ps.应该避免使用多重继承)

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.aa()
c.bb()
c.cc()

12.按照要求修改代码

给定如下代码

class person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def say_score:
        print("I don't know")

将person作为父类,构造一个名为student的子类,并重写say_score方法,调用student的say_score方法时,输出"my score is 150."最后查看student的继承层次结构和实例对象s1的所有属性

输出结果

my score is 150.
[<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__', '_person__age', 'name', 'say_score']

13.说出下列代码的执行结果

代码1

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

p = person('santa')
print(p)

代码2

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

    def __str__(self):
        return 'my name is {0}'.format(self.name)
p = person('santa')
print(p)

14.说出下列代码的执行结果

代码1

class A:
    def aa(self):
        print('aa')
    def say(self):
        print('AAA')
class B:
    def bb(self):
        print('bb')
    def say(self):
        print('BBB')
class C(B,A):
    def cc(self):
        print('cc')
c = C()
c.say()
print(C.mro())

代码2

class A:
    def aa(self):
        print('aa')
    def say(self):
        print('AAA')
class B:
    def bb(self):
        print('bb')
    def say(self):
        print('BBB')
class C(A, B):
    def cc(self):
        print('cc')
c = C()
c.say()
print(C.mro())

15.使用super()写出输出结果相同的代码

class A:
    def say(self):
        print('A:', self)

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

B().say()

输出结果

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

16.多态是什么?并说出以下代码的结果

class man:
    def eat(self):
        print("吃饭")

class Chinese(man):
    def eat(self):
        print("用筷子")

class European(man):
    def eat(self):
        print("用刀叉")

def maneat(m):
    if isinstance(m, man):
        m.eat()
    else:
        print('不能吃饭')

maneat(Chinese())
maneat(European())

17.一些常见的符号,例如"+,-,*,/“实际上是特殊方法,例如”+"就是__add__()方法,观察以下代码,通过改写__add__()实现字符串的相加,并输出对象p1的

class person:
    def __init__(self, name):
        self.name = name
#此处需要补充代码
p1 = person('santa')
p2 = person('kokoro')
print(p1 + p2)    #相当于p1.__add__(p2)

输出结果

santa--kokoro

回答问题:python对象中包含了很多双下划线开始和结束的属性,这些属性叫什么?

18.说出下列代码的输出结果

import copy
class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

class a:
    def printa(self):
        print('a', self)

class b:
    def printb(self):
        print(b, self)

#测试变量赋值
a1 = a()
a2 = a1
print(a1, a2)

#测试浅拷贝
b1 = b()
A1 = A(a1, b1)
A2 = copy.copy(A1)
print(A1, A1.a, A1.b)
print(A2, A2.a, A2.b)

#测试深拷贝
A3 = copy.deepcopy(A1)
print(A1, A1.a, A1.b)
print(A3, A3.a, A3.b)

#测试组合
A3.a.printa()

19.什么是工厂模式?什么是单例模式?

Keys

1.面向过程,面向对象,函数式编程

2.面向过程适合简单不需要协作的事务,将事务分解为各个步骤,例如开车[1.启动2.挂挡3.踩油门];面向对象首先思考事务的设计,例如造车[车由以下部分组成:1.轮胎2.发动机3.外壳等,然后找轮胎厂,找发动机厂等,协同完成事务,具体到微观的操作,例如造轮胎,仍然需要面向过程的思路]

总结:面向对象的思想解决复杂问题和宏观问题,面向过程思想与之相反

3.个人理解:对象就是把不同类型的数据,方法(函数)放到一起,得到的结果;类就是把不同类型的数据,方法放到一起,总体的一个计算过程.如果对象是饼干,类就是饼干的模具;类是对象的模板

(1)对象的组成:id,type,value[属性(attributes),方法(methods)];(2)__new__()方法和 __init__()方法分别代表创建对象和初始化创建好的对象;实际上__init__()叫做***构造函数***,它包含了__new__()方法和 __init__()方法的两个过程.

(3)[1]__init__()写法固定(两个下划线);[2]第一个参数必须是self,指的是创建好的***实例对象***;[3]构造函数通常用来初始化实例对象的实例属性,无返回值;[4]通过类名()调用构造函数;

(4)***实例属性***是从属于实例对象的属性,也称为实例变量;实例属性一般在__new__()方法中通过如下代码定义[self.实例属性名 = 初始值];在本类其他实例方法中,也是通过self访问[self.实例属性名];创建对象后,通过实例对象访问:[obj = 类名();obj.实例属性名 = 值]

(5)

***实例方法***是从属于实例对象的方法,格式如下

def 方法名(self,[形参列表]):
    函数体

不需要给self传递参数,self由解释器自动传递

s1.say_score()由解释器翻译为student.say_score(s1)

(6)

解释器执行[class 类名:]的时候就会创建一个***类对象***,类对象是实例对象的模板;***类属性***从属于类对象,可以被所有实例对象共享,类对象的定义方式如下:

class 类名:
    类变量名 = 初始值

可以通过[类名.类对象名]来读写,内存分析图如下所示

在这里插入图片描述

(7)类方法从属于类对象,格式如下:

@classmethod
def 类方法名(cls[,形参列表]):
    函数体

类方法的调用格式[类名.类方法名(参数列表)],不需要也不能给cls传值;类方法中访问实例属性和实例方法会报错

子类继承父类方法时,传入cls是子类对象,不是父类对象(还没有学)

(8)静态方法和普通函数的区别是需要通过类调用,格式如下

@staticmethod
def 静态方法名([形参列表]):
    函数体

静态方法中访问实例属性和实例方法会报错

(1)输出结果

销毁对象:<__main__.person object at 0x000001F498155898>
程序结束
销毁对象:<__main__.person object at 0x000001F498155860>

首先销毁了p2,程序结束之后销毁了p1

(2)当对象没有被引用时(对象的引用计数为0,对象被变量引用1次,引用计数就会增加1),由垃圾回收器调用__del__方法;(3)del语句;

(4)输出结果

计算工资
120000

定义了__call__()方法的对象,可以像函数一样被调用,称为可调用对象
6.定义多个重名的方法时,只有最后一个方法有效

7.输出结果

bbb
ccc

8.面向对象的三大特征是***封装,继承,多态***;封装是指隐藏对象的属性和实现细节,只对外提供必需的方法,例如把手机视为对象,手机只显现出摄像头,隐藏了电路板;继承指的是***子类***(也叫***派生类***)具有***父类***(也叫***基类***)的特性;多态是指一个方法调用不同对象产生不同的行为,例如每个人的休息方式不一样

(1)

class employee:
    def __init__(self, name, age):
        self.name = name
        self.__age = age    #两个下划线

e = employee('santa', 18)
print(e.name)
print(e._employee__age)    #类名前一个下划线,类名后两个下划线

输出结果

santa
18

通常两个下划线开头的属性是私有的,其他是公共的;类内部可以访问私有属性;类外部不可以直接访问私有属性/方法,可以通过[_类名__私有属性/方法名]访问私有属性/方法;方法本质上也是属性

(2)

class employee:
    __company = 'santates.corp'
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def __work(self):
        print("aaa")
e = employee('santa', 18)
e._employee__work()
print(e._employee__company)

输出结果

aaa
santates.corp
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 salary >= 0:
            self.__salary = salary
        else:
            print("录入错误")

s1 = employee('santa', 10000)
print(s1.salary)    #注意这里的调用方法
s1.salary = 20000    #像调用属性一样调用方法
print(s1.salary)
s1.salary = -200

(1)

class person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def say_score(self):
        print("I don't know")

class student(person):
    def __init__(self, name, age, score):
        person.__init__(self, name, age)    #必须显式地调用父类的初始化方法
        self.score = score

s1 = student('santa', 25, 99)
s1.say_score()    #调用父类中的方法
print(s1.name)
print(s1._person__age)
print(dir(s1))    #用来查看对象的属性

key:

python支持多重继承,一个子类可以继承多个父类,语法如下

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

如果在类定义中没指定父类,默认父类为***object类***,里面定义了一些所有类共有的默认实现,例如:__new__()

在子类的构造函数中调用父类的构造函数,格式如下

父类名.__init__(self, 参数列表)

(2)

输出结果

aa
bb
cc
class person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    def say_score(self):
        print("I don't know")

class student(person):
    def __init__(self, name, age):
        person.__init__(self, name, age)
    def say_score(self):
        print("my score is 150.")

s1 = student('santa', 18)
s1.say_score()
print(student.mro())

代码1输出结果

<__main__.person object at 0x00000200E4146630>

代码2输出结果

my name is santa

object有一个__str__()方法,用于返回一个对于对象的描述,该方法可以重写

代码1输出结果

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

代码2输出结果

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

等价代码

class A:
    def say(self):
        print('A:', self)

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

B().say()

16.***多态***指的是同一个方法的调用由于对象的不同产生不同的行为

输出结果

用筷子
用刀叉
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 '不能相加'
p1 = person('santa')
p2 = person('kokoro')
print(p1 + p2)    #相当于p1.__add__(p2)

python对象中包含了很多双下划线开始和结束的属性,这些属性叫特殊属性

下列特殊属性供参考:

在这里插入图片描述

输出结果

<__main__.a object at 0x000002410FCC85C0> <__main__.a object at 0x000002410FCC85C0>

<__main__.A object at 0x000002410FEEE940> <__main__.a object at 0x000002410FCC85C0> <__main__.b object at 0x000002410FF1B048>
<__main__.A object at 0x0000024110F7F5C0> <__main__.a object at 0x000002410FCC85C0> <__main__.b object at 0x000002410FF1B048>

<__main__.A object at 0x000002410FEEE940> <__main__.a object at 0x000002410FCC85C0> <__main__.b object at 0x000002410FF1B048>
<__main__.A object at 0x0000024110F7F550> <__main__.a object at 0x0000024110F7F4E0> <__main__.b object at 0x0000024110F7F940>

a <__main__.a object at 0x0000024110F7F4E0>

对象的浅拷贝和深拷贝:

浅拷贝不拷贝子对象,源对象和拷贝对象引用同一个子对象;深拷贝拷贝源对象所有的子对象,源对象和拷贝对象的所有子对象都不同

继承和组合的用法区分:

狗是动物,狗类继承动物类;手机有cpu,则使用***组合***的方法

工厂模式:使用工厂类实现实例类

单例模式:确保一个类只有一个实例并提供一个访问该实例的全局访问点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值