python自学笔记9 —— 面向对象编程

python自学笔记9 —— 面向对象编程

9.0 基本知识
9.0.1 几个常见名词
  1. 类 : 学生
  2. 对象 : 大明 萨姆 李红
  3. 属性 : 身高 体重 爱好
  4. 方法 : 学习 睡觉 吃饭
    其中,所有类要求首字母大写,多个单词组合要求驼峰式命名:
    例如:Students StudentsClass1 Books MyBooks
9.0.2 常见格式
class 类名(父类) :
    #属性
    #方法
9.1 属性
9.1.0 简单的创建与调用
# 定义一个类,类中有类属性
class Student:
    name = 'Daming'
    # 这里的name就是类属性

# 创建一个对象
a = Student() # a就是Student类里的一个对象

# 调用类属性
print(a.name)

# 输出结果为:
# Daming
9.1.1 修改属性

修改对象属性

class Student:
    age = 18
    # 这里的name就是类属性

Daming = Student()
Daming.age = 25
print("Daming's age = ",Daming.age)

Liwei = Student()
print("Liwei's age = ",Liwei.age)

# 输出结果为:
# Daming's age =  25
# Liwei's age =  18

这里可以观察到,修改了Student类的Daming对象的age属性,并不能使Student类的age属性发生改变。
此时修改的是对象属性,类属性不变,但是可以通过以下方法修改类属性。

# 还是上面那个Student类
class Student: 
    age = 18

Student.age = 25
Ammy = Student()
print("Ammy's age = ",Ammy.age)

# 输出结果为:
# Ammy's age =  25

此时Student类的age属性已经发生改变

9.2 方法
  1. 方法的定义与之前定义函数一样
  2. 方法中的第一个输入参数必须为self
9.2.0 简单的创建与调用
# 一个简单的面向对象方法代码
class Classmates():
    def func1(self):
        print("我爱python")

    def func2(self):
        print("python也爱我")

student1 = Classmates()
student1.func1()
student1.func2()

# 输出结果为:
# 我爱python
# python也爱我
9.3 魔术方法

什么是魔术方法?

  1. 形式例如 init(self)
  2. 已经由python库写好,用户不能随意更改
魔术方法1 init(self)

当创建一个对象时,都会执行一遍类的__init__(self)函数,作用类似于初始化.

class Class():
    def __init__(self):
        print("正在执行inti函数")
        print("打印self",self)

class1 = Class()

print("打印class1",class1)

# 输出结果为:
# 正在执行inti函数
# 打印self <__main__.Class object at 0x000002B58DA47EB0>
# 打印class1 <__main__.Class object at 0x000002B58DA47EB0>

从输出结果来看:

  1. 该程序中,我们并没有调用class1中的__init__(self),只是打印了class1,这印证了 : 当创建一个对象时,都会执行一遍类的__init__(self)函数,作用类似于初始化.
  2. 通过打印,我们发现,self就是class1.也就是说,self的实质就是生成的对象.

改写 init(self) —> 函数在创建对象的同时就可以设置对象的属性

class Students:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def printer(self):
        print("学生姓名为 {0},学生年龄为 {1}".format(self.name,self.age))

student = Students("Tom",11)
student.printer()

# 输出结果为:
# 学生姓名为 Tom,学生年龄为 11
魔术方法2 del(self)

当调用del语句删除对象时,就会执行类的这个函数,我们也可以改写这个函数

class Students:
    def __del__(self):
        print("我们删掉了这个对象!")
student = Students()
del student
# 输出结果为:
# 我们删掉了这个对象!
魔术方法3 str(self)

当使用print函数打印对象时,就会执行类的这个函数,我们也可以改写这个函数

class Students:
    def __str__(self):
        return "我们改写了这个方法"
s = Students();
print(s)

# 输出结果为:
# 我们改写了这个方法

我们可以用改写__str__(self)来输出对象的所有属性.

魔术方法4 repl(self)

与魔术方法3 str(self)相似,只不过是顺序问题.例如,在打印对象时,若__str__(self)没有被改写,便会来看__repl__(self)的内容.若两者都没有被改写,则会直接打印对象的地址

魔术方法5 call(self)

直接在对象名后加 () 便可以触发

class Students:
    def __call__(self):
        print("我们改写了这个方法")
s = Students();
s()

# 输出结果为:
# 我们改写了这个方法
9.4 内置属性
内置属性1 slots

限制对象不能添加动态属性

class Students:
    __slots__ = ('name','age')
    def __init__(self,name,age):
        self.name = name
        self.age = age
s1 = Students("Tom","17")
s1.weight = 120

#输出报错
内置属性2 doc

输出类的描述信息

class Students:
    """这里就是输出"""
    def func(self):
        pass

print(Students.__doc__)
#这里就是输出
9.5 私有属性和私有方法
9.5.0 简单的创建

在定义属性或方法时,在属性名或者方法名前增加两个下划线__,定义的就是私有属性或方法。
此时不能通过普通的调用方式来调用私有属性或方法

class Students():
    __name = "abc"
    def __printer(self):
        print("abc")
s1 = Students()
print(s1.__name)
s1.__printer

# 发生报错
9.5.1 访问私有属性和私有方法

法1. 直接访问. 通过在私有属性和私有方法前加_类名,便可以直接访问

class Students():
    __name = "abc"
    def __printer(self):
        print("abcd")
s2 = Students()
print(s2._Students__name)
s2._Students__printer()

# 输出结果为 :
# abc
# abcd

法2. 定义方法访问私有变量

class Students():
    __name = "abc"
    def __printer(self):
        print("abcd")
    def get_name(self): # 使用get_name输出__name
        return self.__name
    def set_name(self, newname): # 使用set_name修改__name
        self.__name = newname
    def get_printer(self): # 使用get_printer输出__printer
        self.__printer()

s1 = Students()

# 测试输出__printer
s1.get_printer()
# 输出成功 : abcd

# 测试输出__name
name1 = s1.get_name()
print(name1)
# 输出成功 : abc

# 测试修改并输出__name
s1.set_name('hhh')
name2 = s1.get_name()
print(name2)
# 输出成功 : hhh
9.6 类方法

需要用 @classmethod 来装饰,且第一个参数必须为cls(类),其他参数必须为类参数(可以是私有参数)

class Students():
    __name = "abc"
    @classmethod
    def printer(cls):
        print(Students.__name)

Students.printer() # 通过类来调用类方法
d = Students()
d.printer() # 通过对象来调用类方法

# 输出结果为 :
# abc
# abc
9.7 静态方法

需要用 @staticmethod 来装饰,不需要类参数(cls)或者对象参数(self)

class Students():
    @staticmethod
    def printer():
        print("这是一个静态方法!")

Students.printer() # 通过类来调用类方法
s = Students()
s.printer() # 通过对象来调用类方法

# 输出结果为 :
# 这是一个静态方法!
# 这是一个静态方法!
9.8 new与init

__new__方法输出实例化对象
__init__方法的输入为实例化对象
即 先有 new 再有 init

9.9 继承

面向对象的三个基本特征 : 继承 多态 封装

9.9.1 单继承
class School(object): # object是python的基类,即所有类都是object的对象,故 万物皆对象
    school_name = "DK8"
    def printer(self):
        print("Dalian K8 welcome to you!")
class Three1(School): # Three1是School的一个子类,可以调用School中的方法和属性
    pass

t = Three1()
t.printer()
print(t.school_name)

# 输出结果为 :
# Dalian K8 welcome to you!
# DK8
9.9.2 继承的传递性
class School(object): # object是python的基类,即所有类都是object的对象,故 万物皆对象
    school_name = "DK8"
    def printer(self):
        print("Dalian K8 welcome to you!")
class Three1(School): # Three1是School的一个子类,可以调用School中的方法和属性
    pass
class Student(Three1): # Student是Three1的一个子类,可以调用Three1中的方法和属性
    pass

s = Student()
s.printer()
print(s.school_name)

# 输出结果为 :
# Dalian K8 welcome to you!
# DK8

这里我们可以看到,Student是Three1的子类,而Three1又是School的子类,但是Student可以直接调用School中的方法和属性,故继承具有传递性。

9.9.3 多重继承
class Class1():
    def printer1(self):
        print("here is class1")
class Class2():
    def printer2(self):
        print("here is Class2")
class Student(Class1,Class2):
    pass

s = Student()
s.printer1()
s.printer2()

# 输出结果为 :
# here is class1
# here is Class2

重继承中,应该避免多个父类中含有函数名一样的方法。
当这种情况存在时,将以最后一个父类的函数为准。

9.10 多态

当多个对象需要执行一类动作时,有以下两种方式
法一

class Class(object):
    def write1(self,student):
        student.writer1()
    def write2(self, student):
        student.writer2()

class Student1(object):
    def writer1(self):
        print("Student1 is here")
class Student2(object):
    def writer2(self):
        print("Student2 is here")

class1 = Class()
s1 = Student1()
s2 = Student2()

class1.write1(s1)
class1.write2(s2)

# 输出结果为 :
# Student1 is here
# Student2 is here

这样代码并没有问题
但是当我们的学生(Student)多了起来时,他们每个人的方法都不一样
我们需要在Class类里加代码
这样做拓展性太低
于是有了面向对象的多态性(利用了继承)
即法二

class Student(object):
    def writer(self):   # 父类提供统一方法,即使是空函数
        pass
class Student1(Student):
    def writer(self):   # 子类重写父类方法
        print("Student1 is here")
class Student2(Student):
    def writer(self):   # 子类重写父类方法
        print("Student2 is here")
class Student3(Student):
    def writer(self):   # 子类重写父类方法
        print("Student3 is here")
s1 = Student1()
s2 = Student2()
s3 = Student3()

s1.writer()
s2.writer()
s3.writer()

# 输出结果为 :
# Student1 is here
# Student2 is here
# Student3 is here
9.11 对象的内置函数
9.11.1 身份运算符 is

用于判断两个对象是否为同一个对象

class Student():
    def __init__(self,name):
        self.name = name
        pass
    def printer(self):
        print(self.name)
s1 = Student("abc")
s2 = Student("abc")
s3 = s1
print(s1 is s2)
print(s1 is s3)

# 输出结果为 :
# False
# True

可以看出,比较的依据并不是对象的内容,而是对象所在的地址。

9.11.2 isinstance

用于判断一个对象是否是由某一个类(或者它的子类)创建出来的。

class Student():
    def __init__(self,name):
        self.name = name
        pass
    def printer(self):
        print(self.name)

class School():
    def __init__(self, name):
        self.name = name
        pass
    def printer(self):
        print(self.name)

s1 = Student("abc")

print(isinstance(s1,Student))
print(isinstance(s1,School))

# 输出结果为 :
# True
# False
9.11.3 issubclass

用于判断一个类是否为另一个类的子类。

class School(object):
    def __init__(self, name):
        self.name = name
        pass
    def printer0(self):
        print(self.name)

class Student(School):
    pass

print(issubclass(Student,School))
print(isinstance(School,Student))

# 输出结果为 :
# True
# False
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值