欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python_面向对象

程序员文章站 2022-07-10 08:23:37
...

类的定义

Python使用class关键字来定义类,class关键字之后是一个空格,接下来是类的名字,如果派生(继承)自其他基类的话,则需要把所有基类放到一对圆括号中并使用逗号分隔,然后是一个冒号,最后换行并定义类的内部实现。类的首字母一般要大写

语法格式 :

class 类名(object):
定义构造方法,实例化时初始化类的属性
      def 两个下划线+init+两个下划线(self, 属性):
      self.属性 = 属性

定义类的方法
      def 方法名(self):
      方法体

创建实例/对象
对象名 = 类名(参数)


调用方法
对象名.方法名()


添加属性或修改属性
对象名.属性名 = 属性


删除属性
del 对象名.属性名

示例

class Student(object):
	# 定义构造方法
	def __init__(self, name, score):
		self.name = name
		self.score = score
	# 定义方法
	def printInfo(self):		
		print("%s :  %d" % (self.name, self.score))
 
# 创建两个个对象
stu1 = Student("小白", 99)
stu2 = Student("小安", 80)
 
# 调用方法
stu1.printInfo()
 
# 添加属性;在stu1对象中添加的新属性,只在stu1中生效,在别的对象中不能使用
stu1.age = 18 
print(stu1.age)
# print(stu2.age)
 
# 修改属性;#在stu1中修改的属性同样只在stu1中生效,与别的对象无关
stu1.name = "小黑"
stu1.printInfo()#>>>小黑 :  99
stu2.printInfo()#>>>小安 :  80
 
# 删除属性;在stu1中删除的属性同样只在stu1中生效,与别的对象无关
del stu1.name
# print(stu1.name)

print(stu2.name)

❤️ 注意 __init__方法的第一个参数永远是self,表示创建的实例本身(类似Java中的this),因此,在__init__方法内部,就可以把各种属性绑定到self,
因为self就指向创建的实例本身;某个对象调用其方法时,Python解析器会把这个对象名作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解析器自己会把实例对象名传进去。
在类的定义中,__init__并不是必需的。只有当需要区分由该类创建的不同对象时,才需要指定__init__方法

数据成员-实例变量与类变量

数据成员可以大致分为两类:属于对象的数据成员(实例变量)和属于类的数据成员(类变量);实例变量主要指在构造函数__ init __()中定义的(当然也可以在其他方法中定义),定义和使用时必须以self作为前缀(这一点是必须的),同一个类的不同对象(实例)之间的数据对象成员之间互不影响;属于类的数据对象是该类所有对象共享的,不属于任何一个对象,在定义类时这类数据成员不在任何一个成员方法的定义中。在主程序中或类的外部,实例变量成员属于实例,只能通过对象名访问;而类变量成员属于类,可以通过类名或对象名访问。另外,在Python中可以动态地为类和对象增加成员

class Student(object):
       name = “UserPython” #类变量–属于类的数据成员
       age = 18

      def __init __ (self, age):
            self.age = age #实例变量–属于对象的数据成员

      def printInfo(self):
            print("%s" % self.age)


不用创建实例即可直接访问类变量
print(Student.name)
>>>UserPython

可以通过“对象名.类变量”访问类变量;优先访问实例变量,如果实例变量没有再访问类变量
stu1 = Student(19)
print(stu1.name, stu1.age)
>>>UserPython 19

通过stu1修改类变量,其实并不是真的修改了类变量,而是在stu1中新创建了一个name实例变量,这个与类变量无关,与其他实例对象无关
stu1.name = “HHHH”
print(stu1.name, Student.name)
>>>HHHH UserPython

stu2 = Student(20)
print(stu2.name)
print(Student.name)
>>>UserPython,因为stu2中没有添加实例变量name,所以返回的是类变量name
>>>UserPython

直接修改类变量
Student.name = “UUUU”
print(stu1.name)
print(Student.name)
>>>HHHH 因为优先访问实例变量所以还是返回“HHHH”
>>>UUUU

私有属性与私有方法

在定义类的成员时,如果成员以两个下划线(__)开头,则表示是私有成员,但是Python并有对私有成员提供严格的访问保护机制。Python提供了一种特殊方式“对象名._类名 __XXX”可以访问私有成员,但这会破坏类的封装性。

class Student(object):
       def init(self, name, age):
             self.__name = name #在属性的前面加上两个下划线即可让该属性变成私有属性
             self.age = age

      def __ del __(self):
             pass

如果想获取私有属性可以定义一个方法来访问私有属性,因为同一个类中,私有属性是可见的,只是在类外部私有属性不可访问
       def getName(self):
             print(self.__name)

同样的想修改私有属性,可以通过定义一个方法来修改
       def setName(self, name):
             self.__name = name

      def printInfo(self):
            print("%s : %d" % (self.__name, self.age))

在方法的前面加上两个下划线即可让该方法变成私有方法,外部无法访问
       def __showInfo(self):
             print("%s : %d" % (self.__name, self.age))


stu1 = Student(“小白”, 18)
stu1.printInfo()
>>>小白 : 18

print(stu1.__name) #不能再访问私有属性
print(stu1.age) #非私有属性依旧可以访问

stu1.getName() #可以通过定义一个方法访问私有属性
stu1.setName(“小小白”)
stu1.printInfo()
>>>小小白 : 18

方法

析构方法

import time
class Test(object):
	def __init__(self, name):
		self.name = name
	def __del__(self):
		print("%s已经被kill了" % self.name)#此句可不写,默认为空语句即可
 
	def printInfo(self):
		print("你的名字为:%s" % self.name)
 
test1 = Test("小白")
test1.printInfo()
 
# del test1 #手动删除一个对象时,是即时调用__del__()方法删除该对象,而不是等程序结束再删除
 
test2 = Test("小黑")
test2.printInfo()
 
# 模拟程序还有其他代码
for t in range(100):
	print(t)
	time.sleep(0.1)

❤️ 如果程序在运行过程中,没有手动调用del来删除一个对象时,而Python解析器检测到该对象又没有任何用处了,那么解析器就会在程序运行结束时,自动调用__del__()方法把这个对象kill掉,为什么要等到程序结束才kill呢?因为解析器还要检查后面的程序是否还有用到该对象嘛!



静态方法

静态方法:实际上跟类没什么关系,只是名义上归类管理可以通过对象名调用静态方法,实际上在静态方法里访问不了类或实例中的任何属性

class People(object):
      def __ init__(self, name):
            self.name = name

      @staticmethod
      def talk(self):
            print("%s is talking" % self.name)


people = People(“UserPython”)
people.talk(people)
>>>UserPython is talking



类方法

只能访问类变量,不能访问实例变量

class People(object):
      name = “UserH”

      def __ init__(self, name):
            self.name = name
            print(“实例变量self.name>>>%s” % self.name)

      @classmethod
      def talk(self):
            print("%s is talking" % self.name)


people = People(“UserPython”)
people.talk()
>>>实例变量self.name==>UserPython
>>>UserH is talking



属性方法

把一个方法变成一个静态属性

class People(object):
      def __ init__(self, name):
            self.name = name
            self.__friend = None

      属性方法:把一个方法变成一个静态属性
      @property
      def talk(self):
            print("%s is talking with %s" % (self.name, self.__friend))

      修改属性方法
      @talk.setter
      def talk(self, friend):
            print("%s is talking with %s" % (self.name, friend))
            self.__friend = friend

       删除属性方法
      @talk.deleter
      def talk(self):
            del self.__friend


people = People(“UserPython”)

调用的是@property的talk()方法
people.talk
>>>UserPython is talking with None

给属性方法赋值,调用的是@talk.setter的talk()方法
people.talk = “UserH”
>>>UserPython is talking with UserH

people.talk
>>>UserPython is talking with UserH

删除属性方法
del people.talk

people.talk
>>>AttributeError: ‘People’ object has no attribute ‘_People__friend’ (说明删除成功)



继承

继承可以让子类全部获取父类的功能,相当于在子类中复制粘贴了父类的代码,也可以重写父类不合适的代码

父类
class People(object):
      构造方法
       def __ init__(self, name, age):
            self.name = name
            self.age = age

      def sayHello(self):
            print(“你好!我是一个People”)

子类继承父类
class Student(People):
       重构父类构造方法
      def __ init__(self, name, age, score):
            super(Student, self).__ init__(name, age) #方法一(建议使用)
            People.__init __(self, name, age) #方法二

            self.score = score

      重写父类方法
       def sayHello(self):
            super(Student, self).sayHello() #保留父类方法中的内容,继承父类的方法,方法一
            #People.sayHello(self) 方法二
            print(“你好!我是一个学生”) #重写的内容或添加的内容


stu1 = Student(“UserPython”, 18, 23)



多继承

父类
class People(object):
      def sayHello(self):
            print(“你好!我是一个People”)

class Man(object):
       def showMe(self):
            print(“你好!我是一个男人”)

子类多继承
class Student(People, Man): #多继承
       pass


stu1 = Student()

stu1.sayHello()
stu1.showMe()

>>>你好!我是一个People
>>>你好!我是一个男人



多继承顺序

class A(object):
       def __ init__(self):
              print(“AAAAA”)

class B(A):
      # def __ init__(self):
            # print(“BBBBB”)
      pass

class C(A):
       def __ init__(self):
              print(“CCCCC”)
      pass

class D(B, C):
      # def __ init__(self):
             # print(“DDDDD”)
       pass


test = D()
>>>CCCCC

从上面可以看出Python3多继承的顺序为广度优先(即D继承B后,如果发现B中没有所需内容再从继承C中查找,而不是发现B中没有所需内容直接到A中查找,当C中也没有时,才到A中查找),Python2为深度优先继承



多态

class Animal(object):
      def __ init__(self, name):
            self.name = name

      def talk(self):
            pass

python中多态写法
       def animal_talk(obj):
            obj.talk()

class Cat(Animal):
      def talk(self):
            print("%s : miao miao miao …" % self.name)

class Dog(Animal):
      def talk(self):
            print("%s : wang wang wang …" % self.name)


dog = Dog(“小狗”)
Animal.animal_talk(dog) #等价于dog.talk()

cat = Cat(“小猫”)
Animal.animal_talk(cat) #等价于cat.talk()

>>>小狗 : wang wang wang …
>>>小猫 : miao miao miao …

相关标签: 面向对象 Python