python之类运用(八)

本文详细介绍Python面向对象编程的基础知识,包括类的定义、对象的创建、属性与方法、self的作用、构造与析构方法等核心内容。同时讲解了继承与多态的概念及应用,以及类属性与实例属性的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、定义类

定义一个类,格式如下:

class 类名(object):

    属性列表

    方法列表

demo:定义一个Car类

class Car(object):

# 属性
wheelNum = 2
color = 'red'

# 方法
def getCarInfo(self):
    print('车轮子个数:%d, 颜色%s'%(self.wheelNum, self.color))

二、创建对象

创建对象的格式为:

对象名 = 类名()

BMW = Car(),这样就产生了一个Car的实例对象,此时也可以通过实例对象BMW来访问属性或者方法了(BMW.wheelNum)

打印创建的类:
print(BWM)

<__main__.Carobject at 0x000000000212EE48>

可以获得这个类在内存中的地址(十六进制的数字)

三、属性

1、公有属性:

在类中我们可以定义一些属性,比如:

class people:
    name = 'Tom'
    age = 12

p = people()
print("name=%s, age=%d"%(p.name,p.age))

定义了一个people类,里面定义了name和age属性,默认值分别为’Tom’和12。

在定义了类之后,就可以用来产生实例化对象了,这句p = people( )实例化了一个对象p,然后就可以通过p来读取属性了。这里的name和age都是公有的,可以直接在类外通过对象名访问,如果想定义成私有的,则需在前面加2个下划线 即’__’

2、私有属性
class people:
    __name = 'Tom'
    __age = 12
p = people()
print("name=%s, age=%d"%(p.name,p.age))

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,在Python中,实例的变量名如果以开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

3、类内公有方法调用私有属性

但是如果外部代码要获取name和age怎么办?可以给people类增加get_name和get_age这样的

 class Student(object):
    ...

    def set_name(self, name):
        self.__name= name
    def set_age(self, age):
        self.__age= age

用类内公有的方法调用私有属性,这样可以对参数做检查,避免传入无效的参数:

class People(object):
    ...

    def set_age(self, score):
        if 0 <= name<= 120:
            self.__age= age
        else:
            raise ValueError('bad age')

四、方法

要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:
下面看个例子:

class people:
    __name = 'Tom'
    __age = 12

    def getName(self):
        return self.__name
    def getAge(self):
        return self.__age


p = people()
print p.getName(),p.getAge()

可以用公有的方法调用私有属性,解决私有属性不能再类外直接调用问题

五、 self

(每个类中的方法都要写self)

看如下示例:

# 定义一个类
class Animal:

    # 方法
    def setName(self, name):
        self.name = name

    def printName(self):
        print '名字为:', self.name

# 定义一个函数
def myPrint(animalName):
    animalName.printName()


dog1 = Animal()
dog1.setName('西西')
myPrint(dog1)

dog2 = Animal()
dog2.setName('北北')
myPrint(dog2)

运行结果:

 self

小总结

所谓的self,可以理解为自己

可以把它当做C++中类里面的this指针一样理解,就是对象自身的意思,在用某个对象

调用该方法时,就将该对象作为第一个参数传递给self。

六、魔法方法

1、 构造方法:在创建一个对象时默认被调用,不需要手动调用

__init__()方法是在创建对象后,被默认执行

在创建完对象后init()方法已经被默认的执行了,那么让对象在默认调用init()方法的时候传递一些参数 ,就需要在创建对象时将参数带入

注意到init方法的第一个参数永远是self,表示创建的实例本身,因此,在init方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

有了init方法,在创建实例的时候,就不能传入空的参数了,必须传入与init方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
看例子:

# 定义类
class Car:

# 构造器方法
def __init__(self, newWheelNum, newColor):
    self.wheelNum = newWheelNum
    self.color = newColor

# 方法
def run(self):
    print ('车在跑,目标:夏威夷')

创建对象

BMW = Car(4, 'green')

print ('车的颜色为:',BMW.color)
print ('车轮子数量为:',BMW.wheelNum)

结果为:

车的颜色为: green
车轮子数量为: 4
2、__str__
3、__del__:析构方法

创建对象时,默认调用构造方法;当删除一个对象时,同样也会默认调用一个方法,这个方法为析构方法
demo:

    class Animal():

        # 构造方法
        def __init__(self):
            print '---构造方法被调用---'

        # 析构方法
        def __del__(self):
            print '---析构方法被调用---'

    # 创建对象
    dog = Animal()

    # 删除对象
    del dog
 ---构造方法被调用---
 ---析构方法被调用---

注意:当对一个类创建了多个对象时,所有的对象都被删除,析构方法才会被执行

4、__name__属性,可以拿到函数的名字:

七、继承和多态

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

1、单继承
  • 子类在继承的时候,在定义类时,小括号()中为父类的名字
  • 父类的属性、方法,会被继承给子类
  • 虽然子类,没有构造方法,但是父类有,所以在子类继承父类的时候,其构造方法也会被继承,所以只要创建Bosi的实例对象,就默认执行了那个继承过来的构造方法

比如,我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:

class Animal(object):
    def run(self):
        print 'Animal is running...'

当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:

class Dog(Animal):
    pass

class Cat(Animal):
    pass

对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。

继承有什么好处?最大的好处是子类获得了父类的全部功能。由于Animial实现了run()方法,因此,Dog和Cat作为它的子类,什么事也没干,就自动拥有了run()方法:

dog = Dog()
dog.run()

cat = Cat()
cat.run()

运行结果如下:

Animal is running...
Animal is running...

当然如果创建的对象觉得父类中的方法不能满足要求时,可以对父类方法进行重写:

class Dog(Animal):
    def run(self):
        print("dog is run...")

class Cat(Animal):
    def run(self):
        print("cat is run ....")
dog = Dog()
dog.run()

cat = Cat()
cat.run()

运行结果如下:

dog is running...
cat is running...

当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。我们说这个过程是子类重写父类,并且我们也获得了继承的另一个好处:多态。

要理解什么是多态,我们首先要对数据类型再作一点说明。当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样:

a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型

在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:
Dog可以看成Animal,但Animal不可以看成Dog。

2、多继承

那么一个子类可不可以有多个父类,就像你既继承了母亲的遗产,又继承了父亲的遗产,在python中也可以继承多个类

  • python中是可以多继承的
  • 父类中的方法、属性,子类会继承

Python中多继承的格式如下:




    # 定义一个父类
    class A:
        def printA(self):
            print '----A----'

    # 定义一个父类
    class B:
        def printB(self):
            print '----B----'

    # 定义一个子类,继承自A、B
    class C(A,B):
        def printC(self):
            print '----C----'

    obj_C = C()
    obj_C.printA()
    obj_C.printB()
运行结果:

    ----A----
    ----B----

如果在上面的多继承例子中,如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,调用哪个?

在python3中,所执行的是广度调用,而且调用的顺序是从左到右,先去父类A中找,如果没有再去父类B中找,如果AB都没找到,程序会抛出异常


继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;

有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;

旧的方式定义Python类允许不从object类继承,但这种编程方式已经严重不推荐使用。任何时候,如果没有合适的类可以继承,就继承自object类。


一个类继承多个类,当调用一个方法时,会有个搜索的顺序,可以用 创建的对象.__mro__来查看,他搜索的顺序

设计类时,尽可能不要出现相同的方法

多态补充
class Dog(object):
    def print_self(self):
        print("大家好,我是xxxx,希望以后大家多多关照....")

class Xiaotq(Dog):
    def print_self(self):
        print("hello everybody, 我是你们的老大,我是xxxx")


def introduce(temp):
    temp.print_self()


dog1 = Dog()
dog2 = Xiaotq()

introduce(dog1)
introduce(dog2)

八、 类属性、实例属性

在了解了类基本的东西之后,下面看一下python中这几个概念的区别

先来谈一下类属性和实例属性

在前面的例子中我们接触到的就是类属性,顾名思义,

1、类属性

类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,在类外可以通过类对象和实例对象访问

类属性一般写在class里面,del(方法)外面,可以直接:类名.类属性名 调用

class people:
    name = 'Tom'  #公有的类属性
    __age = 12     #私有的类属性
p = people()

print p.name             #正确
print people.name        #正确
print p.__age            #错误,不能在类外通过实例对象访问私有的类属性
print people.__age       #错误,不能在类外通过类对象访问私有的类属性
2、实例属性

实例属性写在 del 内,必须实力化类之后才可以被实例化之后的对象调用

实例属性是不需要在类中显示定义的,比如:

在类外对类对象people进行实例化之后,产生了一个实例对象p,然后p.age = 12这句给p添加了一个实例属性age,赋值为12。这个实例属性是实例对象p所特有的,注意,类对象people并不拥有它(所以不能通过类对象来访问这个age属性)。当然还可以在实例化对象的时候给age赋值。

class people:
    name = 'Tom'

    #__init__()是内置的构造方法,在实例化对象时自动调用
    def __init__(self,age):
        self.agep = people(12)
print p.name    #正确
print p.age     #正确

print people.name    #正确
print people.age     #错误

外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

class people:
    country = 'china'

print people.country
p = people()
print p.country
p.country = 'japan' 
print p.country      #实例属性会屏蔽掉同名的类属性
print people.country
del p.country    #删除实例属性
print p.country

注意:
在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。


总结

实例属性属于各个实例所有,互不干扰;

类属性属于类所有,所有实例共享一个属性;

不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。

类方法
 https://www.cnblogs.com/scolia/p/5598114.html

类三种方法语法形式

class Foo(object):
    """类三种方法语法形式"""

    def instance_method(self):
        print("是类{}的实例方法,只能被实例对象调用".format(Foo))

    @staticmethod
    def static_method():
        print("是静态方法")

    @classmethod
    def class_method(cls):
        print("是类方法")

foo = Foo()
foo.instance_method()
foo.static_method()
foo.class_method()
print('----------------')
Foo.static_method()
Foo.class_method()


作者:python爱好者
链接:https://www.jianshu.com/p/212b6fdb2c50
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

九、调用被重写的方法

class Animal:
    def eat(self):
        print("-----吃----")
    def drink(self):
        print("-----喝----")
    def sleep(self):
        print("-----睡觉----")
    def run(self):
        print("-----跑----")

class Dog(Animal):
    def bark(self):
        print("----汪汪叫---")


class Xiaotq(Dog):
    def fly(self):
        print("----飞----")

    def bark(self):
        print("----狂叫-----")

        #第1种调用被重写的父类的方法
        #Dog.bark(self)

        #第2种
        super().bark()


xiaotq = Xiaotq()
xiaotq.fly()
xiaotq.bark()
xiaotq.eat()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值