python 类

本文详细介绍了Python面向对象编程的关键概念,包括类变量的查找顺序,实例方法、类方法和静态方法的区别,成员变量的可见性以及继承机制。通过示例代码展示了如何在类中定义和使用变量,以及如何调用不同类型的函数。同时,探讨了Python中私有变量的实际访问情况,强调了动态语言特性的影响。最后,通过一个简单的继承示例展示了子类如何继承并扩展父类的方法。
摘要由CSDN通过智能技术生成

 

一、类与对象的变量查找顺序

class Student():
    name = 'Delphi'
    age = 30

    def __init__(self,name='',age=''):
        name=name
        age=age

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")


student = Student()
print(Student.name) # 这个打印出来Delphi 很正常
print(student.name) # 为什么这个也会打印出来Delphi呢?

print(student.name) # 为什么这个也会打印出来Delphi呢?

类与对象的变量查找顺序:先在对象变量里面去查找,发现没有找到!因为在构造函数中,赋值方式少了self.name=name 。然后python 解释器会类里面去找。发现类变量里面定义了 name = 'Delphi',所以打印出来就是Delphi 了。补充一点:如果在Student 类里面也没有找到,并且如果Student 这个类有父类,那么python解释器会到Student 这个类的父类中去查找。如下面的代码例子:



class Parent():
    name = 'Parent'

class Student(Parent):
    age = 30

    def __init__(self,name='',age=''):
        name=name
        age=age

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")


student = Student()
print(student.__dict__)
print(Student.name) # 这个打印出来Parent 很正常
print(Student.__dict__)
print(student.name) # 为什么这个也会打印出来Parent呢?
class Student():
    sum = 0

    def __init__(self,name='',age=''):
        self.name=name
        self.age=age
        #self.sum=980
        #print("sum=",sum) # 这样访问不到类成员变量sum
        self.__class__.sum += 1
        print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    def get_sum(self):
        print("sum=",self.sum)


student = Student('Delphi',23)
print(student.sum)
print('Student.sum=',Student.sum)
student = Student('Delphi',23)

二、类方法和实例方法

决定一个类中的函数是类方法还是实例方法,取决于这个函数前面是否有 @classmethod ,这种写法也叫做装饰器。demo如下。那么Python中为什么需要搞一个类方法出来呢?其实主要是为了方便操作类变量。

实例方法关联的是类对象,而类方法关联的是类本身。实例方法第一个参数self,代表的是当前对象。而类方法第一个参数cls,代表的是当前类。

class Student():
    sum = 0

    def __init__(self,name='',age=''):
        self.name=name
        self.age=age
        #self.sum=980
        #print("sum=",sum) # 这样访问不到类成员变量sum
        self.__class__.sum += 1
        print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    def get_sum(self):
        print("sum=",self.sum)

    @classmethod
    def plus_sum(cls): # 当然这个cls ,可以改为self
        cls.sum += 1  # 这样写,可以直接操作类成员变量sum,而不需要在类实例方法中,像self.__class__.sum += 1 来操作类成员变量
        print("类成员方法,得到的结果为:",cls.sum)


student = Student('Delphi',23)
print(student.sum)
print('Student.sum=',Student.sum)
student1 = Student('Delphi',23)
student1.plus_sum()  #虽然对象也能够调用类方法,但是不建议这么做;还是要准守python良好的编程习惯,对象调用实例方法,类调用类方法
Student.plus_sum()

三、静态方法

1.静态方法,没有像实例方法和类方法那样,第一个参数必须传进来一个self,或者是cls。

2.静态方法前面必须加上,@staticmethod 关键字

3.类 和 对象 都能够调用静态方法

4.静态方法的内部是可以访问类变量

5.静态方法和类方法中是不能够访问实例变量的。

class Student():
    sum = 0

    def __init__(self,name='',age=''):
        self.name=name
        self.age=age
        #self.sum=980
        #print("sum=",sum) # 这样访问不到类成员变量sum
        #self.__class__.sum += 1
        #print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    @classmethod
    def plus_sum(cls): # 当然这个cls ,可以改为self
        cls.sum += 1  # 这样写,可以直接操作类成员变量sum,而不需要在类实例方法中,像self.__class__.sum += 1 来操作类成员变量
        print("类成员方法,得到的结果为:",cls.sum)
        #验证类方法是否能够访问实例变量
        print("cls.name=",cls.name)

    @staticmethod
    def add(x,y):
        print("cls.name=", Student.name)
        print("this is a staticmethod:")

student = Student('Delphi',23)
student.add(1,2)
Student.add(1,2)
Student.plus_sum()

四、成员(变量和方法)可见性公开和私有。

1.成员方法如果前面有2个双下划线,则表示为私有的;如果在后面同时也加上两个双下划线这表示为公有的,这就是为什么构造函数,__init__(self),能够在外面直接被调用的原因了。

class Student():
    sum = 0

    def __init__(self,name='',age=0):
        self.name=name
        self.age=age
        self.__score=0
        #print("sum=",sum) # 这样访问不到类成员变量sum
        self.__class__.sum += 1
        #print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def marking(self,score):
        if score < 0:
            print("socre must be > 0 !")
            return
        self.__score=score
        print(self.name+" score is:"+str(self.__score))
        return self.__score

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    @classmethod
    def plus_sum(cls): # 当然这个cls ,可以改为self
        cls.sum += 1  # 这样写,可以直接操作类成员变量sum,而不需要在类实例方法中,像self.__class__.sum += 1 来操作类成员变量
        print("类成员方法,得到的结果为:",cls.sum)
        #验证类方法是否能够访问实例变量
        print("cls.name=",cls.name)

    @staticmethod
    def add(x,y):
        print("cls.name=", Student.name)
        print("this is a staticmethod:")

student = Student('Delphi',23)
student.marking(78)
student.__score=90 # 为什么定义了socre 为私有的,还是不会报错呢???

解决上述问题:为什么定义了socre 为私有的,还是不会报错呢???

1.由于python是动态语言的特性,因为这样写:

student.__score=90 # 为什么定义了socre 为私有的,还是不会报错呢???

Python 会重新生成一个实例变量 __score,并且这个重新生成的实例变量为公有属性。

2.可以看下面的demo 来验证以上的说法:

class Student():
    sum = 0

    def __init__(self,name='',age=0,score=0):
        self.name=name
        self.age=age
        self.__score=score
        #print("sum=",sum) # 这样访问不到类成员变量sum
        self.__class__.sum += 1
        #print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def marking(self,score):
        if score < 0:
            print("socre must be > 0 !")
            return
        self.__score=score
        print(self.name+" score is:"+str(self.__score))
        return self.__score

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    @classmethod
    def plus_sum(cls): # 当然这个cls ,可以改为self
        cls.sum += 1  # 这样写,可以直接操作类成员变量sum,而不需要在类实例方法中,像self.__class__.sum += 1 来操作类成员变量
        print("类成员方法,得到的结果为:",cls.sum)
        #验证类方法是否能够访问实例变量
        print("cls.name=",cls.name)

    @staticmethod
    def add(x,y):
        print("cls.name=", Student.name)
        print("this is a staticmethod:")

student = Student('Delphi',23,80)
student1 = Student('Delphi',23,81)
student.marking(78)
student.__score=90 # 为什么定义了socre 为私有的,还是不会报错呢???
print(student.__score)
print(student.__dict__) #{'name': 'Delphi', 'age': 23, '_Student__score': 78, '__score': 90}
print(student1.__dict__) #{'name': 'Delphi', 'age': 23, '_Student__score': 81} 此时并没有 '__score' 这个属性
print(student1.__score) #此时打印student1.__score 会报错

3.没有什么是不能访问的

1.从上面的代码可以看出来,student1.__dict__ 没有__score 这个属性,导致python编译器会报错。

2.我们也可以看出,__score,之所以会成为私有的,是因为__score,会被python编译器替换成 _Student__score,相当于换了一个名字,所以在外面就不能够访问__score 这个属性了。

3.那么基于2 我们可以推倒出来,我们直接在外面访问 _Student__score ,那么也相当于访问了私有实例变量 __score。

综上:所以才说没什么是不能访问的,代码实例如下:

class Student():
    sum = 0

    def __init__(self,name='',age=0,score=0):
        self.name=name
        self.age=age
        self.__score=score
        #print("sum=",sum) # 这样访问不到类成员变量sum
        self.__class__.sum += 1
        #print('当前班级的学生人数:', self.__class__.sum) # 这样可以访问到类成员变量 sum

    def marking(self,score):
        if score < 0:
            print("socre must be > 0 !")
            return
        self.__score=score
        print(self.name+" score is:"+str(self.__score))
        return self.__score

    def do_homework(self):
        print(self.name+","+str(self.age)+",student do homework...")

    @classmethod
    def plus_sum(cls): # 当然这个cls ,可以改为self
        cls.sum += 1  # 这样写,可以直接操作类成员变量sum,而不需要在类实例方法中,像self.__class__.sum += 1 来操作类成员变量
        print("类成员方法,得到的结果为:",cls.sum)
        #验证类方法是否能够访问实例变量
        print("cls.name=",cls.name)

    @staticmethod
    def add(x,y):
        print("cls.name=", Student.name)
        print("this is a staticmethod:")

student = Student('Delphi',23,80)
student1 = Student('Delphi',23,81)
student.marking(78)
student.__score=90 # 为什么定义了socre 为私有的,还是不会报错呢???
print(student.__score)
print(student.__dict__)
print(student1.__dict__) # 此时并没有 '__score' 这个属性
print(student1._Student__score) #此时打印student1.__score 会报错

五、继承

demo1:

Human.py 代码如下:


class Human():
    sum = 0
    def __init__(self,name='',age=0):
        self.name = name
        self.age = age

    def get_name(self):
        print(self.name)

main.py 代码如下:


from Human import Human

class Student(Human):
    def __init__(self,name,age,school=''):
        self.school = school
        Human.__init__(self,name,age)

    def do_homework(self):
        print(self.name + " is do homework.")

    def get_school(self):
        print(self.name + " school is : "+self.school)


student1 = Student("Delphi",23,"beijing school")
student1.do_homework()
student1.get_school()

2.子类方法调用父类方法super关键字

Human.py 代码如下:


class Human():
    sum = 0
    def __init__(self,name='',age=0):
        self.name = name
        self.age = age

    def get_name(self):
        print(self.name)

    def do_homework(self):
        print("do_homework,This is parent method")

main.py 代码如下:


from Human import Human

class Student(Human):
    def __init__(self,name,age,school=''):
        self.school = school
        #Human.__init__(self,name,age) 不推荐这样调用父类的构造函数
        super(Student,self).__init__(name,age) # 推荐这样调用父类的构造函数

    def do_homework(self):
        super(Student, self).do_homework()  # 调用父类的构造函数
        print(self.name + " is do homework.")

    def get_school(self):
        print(self.name + " school is : "+self.school)


student1 = Student("Delphi",23,"beijing school")
student1.do_homework()
student1.get_school()
#Student.get_school(student1) #不推荐这样写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值