详细得让你惊叹的“python”面向对象介绍(带图)

面向对象

定义类

语法:
class 类名:
类中成员
类中的成员:实例属性,实例方法,类属性,类方法,静态方法等
下面会把类中的成员全部单独说明,代码都是独立的,为了方便理解!

定义一个类并创建类实例

# 定义一个类,使用class关键字
class Student:
    pass # 暂时不赋值

#创建类的对象
stu1 = Student() # 创建Student类的一个实例
stu2 = Student()
print(stu1,'自定义类型type:',type(stu1))
print(stu2,'自定义类型type:',type(stu2))

# 测试,对比type类型
a = 666
print(a,'默认type:',type(a))
c = '六六六'
print(c,'默认type:',type(c))
print('*' * 59)

在这里插入图片描述

为对象绑定实例属性

# 定义一个类,使用class关键字
class Student:
    pass # 暂时不赋值

#创建类的对象
stu1 = Student() # 创建Student类的一个实例
stu2 = Student()
print(stu1,'自定义类型type:',type(stu1))
print(stu2,'自定义类型type:',type(stu2))

# 为对象绑定属性 (注:需要先给类创建实例)
stu1.name = 'ccx'
stu1.age = 22
stu2.name = 'xgq'
stu2.age = 23
stu2.sex = 'woman'
print('stu1的参数:',stu1.name,stu1.age) #打印stu1的参数
print('stu2的参数:',stu2.name,stu2.sex,stu2.age) # 打印stu2的参数

在这里插入图片描述

创建实例方法以及使用实例方法

  • 下面这方法是默认不传参的方法
# 定义一个类,使用class关键字
class Student:
    #pass # 暂时不赋值
    # 创建实例方法:将self作为第一个参数的方法 (self自动生成)
    def say_hi(self):  # self表示当前类的实例,类似于java中的this
        print('Hi ' + self.name) # 传入name参数。

#创建类的对象
stu1 = Student() # 创建Student类的一个实例
stu2 = Student()
#print(stu1,'自定义类型type:',type(stu1))
#print(stu2,'自定义类型type:',type(stu2))

# 为对象绑定属性 (注:需要先给类创建实例)
stu1.name = 'ccx'
stu1.age = 22
stu2.name = 'xgq'
stu2.age = 23
stu2.sex = 'woman'
# print('stu1的参数:',stu1.name,stu1.age) #打印stu1的参数
# print('stu2的参数:',stu2.name,stu2.sex,stu2.age) # 打印stu2的参数

#访问实例方法
stu1.say_hi() # 调用方法时无需传递self,由解析器调用时将对象作为self自动传入
stu2.say_hi()

在这里插入图片描述

  • 下面说一下传参的方法

# 定义一个类,使用class关键字
class Student:
    #pass # 暂时不赋值
    # 创建实例方法:将self作为第一个参数的方法 (self自动生成)
    def say_hi(self):  # self表示当前类的实例,类似于java中的this
        print('Hi ' + self.name) # 传入name参数。
    # 创建一个需要传参数的方法
    def say_hello(self,username='默认是hero'): #定义了默认值
        print('hello ',username)

#创建类的对象
stu1 = Student() # 创建Student类的一个实例
stu2 = Student()

# 为对象绑定属性 (注:需要先给类创建实例)
stu1.name = 'ccx'
stu2.name = 'xgq'

# 调用不需要传参的方法
stu1.say_hi()
stu2.say_hi()
#调用传参的方法
stu1.say_hello() # 不传参也不会报错
stu2.say_hello('崔') # 传参

在这里插入图片描述

类属性

# 定义一个类,使用class关键字
class Student:
    # 类属性:直接在类中定义的属性,可以通过类或者实例对象来访问
    boy = 'good enveving '

stu1 = Student()  # 创建一个类对象
stu2 = Student()

# 访问类属性
print(Student.boy)
stu1.boy = '晚上好' #stu1添加了一个实例属性,并不会改变类属性中boy的值
print(stu1.boy)
print(stu2.boy) # 如果当前实例没有boy属性,则会向上查找类属性boy

在这里插入图片描述

类方法

# 定义一个类,使用class关键字
class Student:
    # 类属性:直接在类中定义的属性,可以通过类或者实例对象来访问
    boy = 'good enveving '

    #类方法:使用@classmethod修饰的方法,将cls作为第一个参数
    @classmethod
    def show(cls, msg):  # cls是默认生成的,表示当前类,msg是自定义传参值
        print(msg,cls.boy)

stu1 = Student()  # 创建一个类对象
stu2 = Student()

# 访问类属性
# print(Student.boy)
# stu1.boy = '晚上好' #stu1添加了一个实例属性,并不会改变类属性中boy的值
# print(stu1.boy)
# print(stu2.boy) # 如果当前实例没有boy属性,则会向上查找类属性boy

#调用类方法
# 通过类调用
Student.show('ccx') #调用方法时候无需传递cls,但定义了msg,所以需要传入一个参数
# 通过对象调用
stu1.show('xgq')

在这里插入图片描述

静态类方法

# 定义一个类,使用class关键字
class Student:
    # 类属性:直接在类中定义的属性,可以通过类或者实例对象来访问
    boy = 'good enveving '

    #类方法:使用@classmethod修饰的方法,将cls作为第一个参数
    @classmethod
    def show(cls, msg):  # cls是默认生成的,表示当前类,msg是自定义传参值
        print(msg,cls.boy)

    # 静态方法:使用@staticmethod修饰的方法,没有任何必选参数,不需要讲cls作为第一参数
    @staticmethod
    def show2(msg):  # msg也可以不要
        print(msg,Student.boy) #因为没有cls表示类,要调用类中属性,可以直接类名.属性即可

stu1 = Student()  # 创建一个类对象
stu2 = Student()

#调用类方法
# 通过类调用
Student.show('ccx') #调用方法时候无需传递cls,但定义了msg,所以需要传入一个参数
# 通过对象调用
stu1.show('xgq')
print('*' * 50)
# 调用静态类方法
Student.show2('崔崇鑫') # 通过类调用
stu1.show2('xgq') # 通过对象调用

在这里插入图片描述

构造方法

# 下面__是两个下划线
__int__() :构造方法,在创建对象时会自动调用
class Student:
    #构造方法(函数),不支持重载
    def __init__(self,name,age): #self是自动生成(当前类),name和age是自定义需要初始化的值
        print('创建对象,执行构造方法。。。')
        self.newname = name # 初始化值,必须初始化!!!!!
        self.newage = age

    # 实例方法
    def show(self):
        print(self.newname,self.newage)
        print('mr %s ,年龄 %d' % (self.newname,self.newage))

# 调用构造方法
stu1 = Student('ccx',22) #创建对象并传入2个参数
print(stu1.newname,stu1.newage) #输出
print('*' * 50)

#调用实例方法
stu1.show()

在这里插入图片描述

封装

封装:隐藏对象中一些不希望被外部所访问到的属性,保证数据的安全。

一般定义方法:缺乏隐蔽性,数据不安全

class Student:
    pass

stu1 = Student()
stu1.num = 50
print(stu1.num)

封装方法 :外界看不到数据,更安全

class Student:
    # 定义私有属性
    __num = 50  # 以两个下划线开头,表示对象的隐藏属性,只能在类内部访问

    # 提供getter/setter方法
    def get_num(self):
        return self.__num  # 返回该类的值是定义的__num值

在这里插入图片描述

    # 可以更改__num的值
    def set_num(self, num):
        # 比如你只想输入的值在1-100之间,否则就是默认值
        if 0 < num < 101:
            self.__num = num  # num是传入的参数
            return self.__num
        else:
            self.__num = 50
            return self.__num


stu1 = Student()  # 创建对象

# 调用封装的值
# print((stu1.__num)) # 外类外部无法访问私有属性
print('普通调用:',stu1.get_num())  # 调用普通返回类的值
print('输入66:',stu1.set_num(66))
print('输入666:',stu1.set_num(666))

在这里插入图片描述

继承

继承:使一个类能够获取到其他类中的属性和方法
父类:其实就是一个普通class name(object),父类中object可以省略,所以平常就直接 class name即可
子类继承父类:class name(父类name)

定义父类,子类继承父类的使用

#定义一个Person类,父类(超类,基类)
class Person:
    def __init__(self,name): # 定义私有类
        self.name = name
    def run(self):#定义一个类函数
        print('person:'+ self.name+'正在奔跑啊啊啊')

class Student(Person): #继承自Person
    def __init__(self,name,set,age):# 定义私有类
        #调用父类的构造方法
       # Person.__init__(name) # 方式一:直接指定父类的构造方法
        super().__init__(name)# 方式二:使用super(),推荐使用该方法
        # 自己类中的构造方法且父类中没有的,直接定义即可
        self.set = set
        self.age = age
    def study(self): #定义一个类函数
        print('stadent:' + self.name + '正在学习。。。。')
    def show(self):#定义一个类函数
        print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
    #可以自定义n个类函数 。。。

stu = Student('ccx','man',22)
stu.run() #因为继承了父类,当然也可以直接调用父类函数
stu.study()
stu.show()

在这里插入图片描述

子类重写父类

其实就是在子类中重新编辑一个和父类方法名一摸一样的就可以覆盖父类中的方法内容了,super().父类方法名()就是调用父类方法内容,如果不要该行,则父类方法中内容全部失效。然后在子类方法中定义新的内容。打印该方法 显示的内容就是子类方法内容了。

#定义一个Person类,父类(超类,基类)
class Person:
    def __init__(self,name): # 定义私有类
        self.name = name
    def run(self):#定义一个类函数
        print('person:'+ self.name+'正在奔跑啊啊啊')

class Student(Person): #继承自Person
    def __init__(self,name,set,age):# 定义私有类
        #调用父类的构造方法
       # Person.__init__(name) # 方式一:直接指定父类的构造方法
        super().__init__(name)# 方式二:使用super(),推荐使用该方法
        # 自己类中的构造方法且父类中没有的,直接定义即可
        self.set = set
        self.age = age
    def study(self): #定义一个类函数
        print('stadent:' + self.name + '正在学习。。。。')
    def show(self):#定义一个类函数
        print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
    #可以自定义n个类函数 。。。
    # 重写父类的方法
    def run(self):
        #super().run() #调用父类的方法 ,如果不要该行,那么父类中的该方法内容就不会输出了
        print('new person :'+ self.name+'正在奔跑咯') #新定义方法内容

stu = Student('ccx','man',22)
stu.run() #因为继承了父类,当然也可以直接调用父类函数
stu.study()
stu.show()

在这里插入图片描述

常用的条件判断

#定义一个Person类,父类(超类,基类)
class Person:
    def __init__(self,name): # 定义私有类
        self.name = name
    def run(self):#定义一个类函数
        print('person:'+ self.name+'正在奔跑啊啊啊')

class Student(Person): #继承自Person
    def __init__(self,name,set,age):# 定义私有类
        #调用父类的构造方法
       # Person.__init__(name) # 方式一:直接指定父类的构造方法
        super().__init__(name)# 方式二:使用super(),推荐使用该方法
        # 自己类中的构造方法且父类中没有的,直接定义即可
        self.set = set
        self.age = age
    def study(self): #定义一个类函数
        print('stadent:' + self.name + '正在学习。。。。')
    def show(self):#定义一个类函数
        print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
    #可以自定义n个类函数 。。。
    # 重写父类的方法
    def run(self):
        #super().run() #调用父类的方法 ,如果不要该行,那么父类中的该方法内容就不会输出了
        print('new person :'+ self.name+'正在奔跑咯') #新定义方法内容

stu = Student('ccx','man',22)
stu.run() #因为继承了父类,当然也可以直接调用父类函数
stu.study()
stu.show()

#判断一个对象是否指定类的实例,即判断对象的类型
print(isinstance(stu,Student))
print(isinstance(stu,Person))

# 判断一个类是否是指定类的子类
print(isinstance(Student,Person))
print(isinstance(Person,object))

# object类是所有类的根类,默认所有类都继承自object
print(stu.__doc__) # 输出文件开头注释的内容(""""""),如果没注释,就是None
print(stu.__dict__) # 以字典的形式打印stu的值

在这里插入图片描述

多继承

多继承: 顾名思义,就是说一个类可以继承多个父类,多个父类之间用逗号隔开就好。
注:不建议使用多继承,因为如果 父类A和父类B中方法有一样的,会存在覆盖或存在加载顺序的问题。

# 定义一个父类B
class A:
    def a(self):
        print('a')
# 定义一个父类B
class B:
    def b(self):
        print('b')
# 定义一个类并继承多个父类,用逗号隔开(java中不支持继承多类)
class C(A,B):
    def c(self):
        print('c')

stu = C()
stu.a()
stu.b()
stu.c()

# 类有一个特殊属性 __bases__ 可以用来获取当前类的所有父类
print(C.__bases__)

在这里插入图片描述

多态

多态:可以 以 多种不同形态展示!

class Animal: #定义一个动物类
    def __init__(self,name):
        self.name = name

    def cry(self):
        print('动物在叫啊。。。。')

class Dog(Animal) : # 定义一个类狗,并继承动物类
    def __init__(self,name,age):
        super().__init__(name)
        self.age = age
    def cry(self):
        print('狗在叫。。。汪汪汪')

class Cat(Animal) : # 定义一个类毛,并继承动物类
    def __init__(self,name,sex):
        super().__init__(name)
        self.sex = sex
    def cry(self):
        print('猫在叫。。。呜哇呜哇')

#一个对象可以以不同的形式去呈现,就是多态
def play(name):  # 注意,这是以函数的方法 调用 上面类的
    print(name.name) #以名字返回,只有一个name返回的是内存地址
    name.cry() # 返回类中的 cry方法内容

# 创建对象
dog = Dog('大黄',2)
cat = Cat('喵咪','公')
play(dog)
play(cat)

在这里插入图片描述

魔术方法

什么是Python魔法方法?

魔法方法就如同它的名字一样神奇,总能在你需要的时候为你提供某种方法来让你的想法实现。魔法方法是指Python内部已经包含的,被双下划线所包围的方法,这些方法在进行特定的操作时会自动被调用,它们是Python面向对象下智慧的结晶。初学者掌握Python的魔法方法也就变得尤为重要了。

为什么要使用Python魔法方法?

使用Python的魔法方法可以使Python的自由度变得更高,当不需要重写时魔法方法也可以在规定的默认情况下生效,在需要重写时也可以让使用者根据自己的需求来重写部分方法来达到自己的期待。而且众所周知Python是支持面向对象的语言Python的基本魔法方法就使得Python在面对对象方面做得更好。

魔法方法的一些语法

基础魔法方法(较为常用)

# 下面的__都是2个下划线
__new__(cls[, ...]) 才是实例化对象调用的第一个方法,它只取下 cls 参数,并把其他参数传给 __init__。 __new__很少使用,但是也有它适合的场景(单例模式),尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。
__init__(self[, ...])构造方法,初始化类的时候被调用
__del__(self)析构方法,当实例化对象被彻底销毁时被调用(实例化对象的所有指针都被销毁时被调用)
__call__(self[, args...])允许一个类的实例像函数一样被调用:x(a, b) 调用 x.__call__(a, b)
__len__(self)定义当被 len() 调用时的行为__repr__(self)定义当被 repr() 调用时的行为
__str__(self)定义当被 str() 调用时的行为__bytes__(self)定义当被 bytes() 调用时的行为
__hash__(self)定义当被 hash() 调用时的行为
__bool__(self)定义当被 bool() 调用时的行为,应该返回 TrueFalse
__format__(self, format_spec)定义当被 format() 调用时的行为

属性相关的方法

# 下面的__都是两个下划线
__getattr__(self, name)定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self, name)定义当该类的属性被访问时的行为
__setattr__(self, name, value)定义当一个属性被设置时的行为
__delattr__(self, name)定义当一个属性被删除时的行为
__dir__(self)定义当 dir() 被调用时的行为
__get__(self, instance, owner)定义当描述符的值被取得时的行为
__set__(self, instance, value)定义当描述符的值被改变时的行为
__delete__(self, instance)定义当描述符的值被删除时的行为

比较操作符

# 下面的__都是两个下划线
__lt__(self, other)定义小于号的行为:x < y 调用 x.__lt__(y)
__le__(self, other)定义小于等于号的行为:x <= y 调用 x.__le__(y)
__eq__(self, other)定义等于号的行为:x == y 调用 x.__eq__(y)
__ne__(self, other)定义不等号的行为:x != y 调用 x.__ne__(y)
__gt__(self, other)定义大于号的行为:x > y 调用 x.__gt__(y)
__ge__(self, other)定义大于等于号的行为:x >= y 调用 x.__ge__(y)

类型转换

# 下面的__都是两个下划线
__complex__(self)定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self)定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self)定义当被 float() 调用时的行为(需要返回恰当的值)__round__(self[, n])定义当被 round() 调用时的行为(需要返回恰当的值)

容器类型(一般用于操作容器类)

# 下面的__都是两个下划线
__len__(self)定义当被 len() 调用时的行为(一般返回容器类的长度)
__getitem__(self, key)定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value)定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self)定义当迭代容器中的元素的行为
__reversed__(self)定义当被 reversed() 调用时的行为
__contains__(self, item)定义当使用成员测试运算符(innot in)时的行为

特点:
1 都是以双下划线开头,以双下划线结尾;
2 不需要手动调用,在特定的时机 会自动执行。

  • 特点展示
# 定义一个类
class Person(object) : # object 可以不要,所有父类默认继承object
    def __init__(self,name,age):
        print('__init__')
        self.name = name
        self.age = age


p1 = Person('崔崇鑫',22)
print(p1) 

在这里插入图片描述

  • 功能使用(部分)
    这里只展示部分功能使用,具体的可以参加上面提到的语法,使用方法都一样。
# 定义一个类
class Person(object) : # object 可以不要,所有父类默认继承object
    def __init__(self,name,age):
        print('__init__')
        self.name = name
        self.age = age
    # 将对象转换为字符串时调用,类似于java中的toString()
    def __str__(self): # 如果不转换,则返回的是内存地址
        return 'Person [name=%s,age=%d]' % (self.name,self.age)
    # 在对象使用len()函数时调用
    def __len__(self):
            return len(self.name)
    # 在对象使用repr()函数时调用
    def __repr__(self):
        return 'hello person'
p1 = Person('崔崇鑫',22)
print(p1)
print(len(p1))
print(repr(p1))

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章