【Python】类——面向对象

Python类

格式

class Student ():
    sum=0   # 类变量

    #实例方法:行为与特征
    def __init__(self,n,a):  # 构造函数(特殊实例方法:初始化)
        self.name=n    # 实例变量
        self.age=a

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

变量

刻画特征

类变量

为所有实例共享

类名.变量名         # 调用类变量

实例变量

为每个实例所独有:保存对象特征值

对象名.变量名       # 调用实例变量

请看下面的栗子

class Student ():
    name="zhangsan"    # 在类函数之外定义的变量
    age=0
    def __init__(self,n,a): 
        self.name=n    # self.变量名 定义实例变量
        self.age=a
stu1=Student("lisi",20)
stu2=Student("liufang",21)
print(stu1.name)  # 打印对象下的实例变量
print(stu2.name)  # 打印对象下的实例变量
print(Student.name)  # 打印类下的类变量
list
liufang
zhangsan

在Student类中定义“名字”,“年龄”两个变量没有错误但没有意义

因为类是抽象的客观,而类变量中的“名字”,“年龄”应该是具体的,所以应该是属于具体对象中的,因此应该在实例变量中定义“名字”“年龄”,使它们与对象关联起来。

类变量意义所在↓

class Student ():
    total=0  # 一个班级里所有学生的总数(和类相关的变量)
    def __init__(self,n,a):
        self.name=n
        self.age=a
        Student.total+=1

stu1=Student("lisi",20)
stu2=Student("liufang",21)
print(Student.total)
2          # 通过构造函数的调用次数累加类变量total(不会根据不同对象而初始化改变),反映输入学生个数的总数

方法

描述行为,通常对变量进行运算和逻辑上的一些操作

实例方法

一、定义与调用:

  • 定义实例方法时,需要传入self参数
  • 调用实例方法时,不需要传入self参数

二、变量访问:

  • 访问类变量:

    1. 不能直接使用类变量名

    2. 两种访问方式

       类名.变量名
      
       self.__class__.变量名   # __class__关键字指当前类
      
  • 访问实例变量

    self.变量名   # 实例方法中只能通过self.变量名调用实例变量,读取操作实例变量
    

    **误区:**不能只通过访问self后面的变量名来访问

    举个栗子↓

    class Student ():
        def __init__(self,n,a):
            self.name=n
            self.age=a
            print(self.name)
            print(self.__dict__)
            print(name)
    stu1=Student("lisi",20)
    
    lisi                             #执行第一个print函数
    {'name': 'lisi', 'age': 20}      #执行第二个print函数,显示变量的字典,存在name变量名
    **报错**                         #但执行第三个print通过使用name变量名仍然会报错
    

self“关键字”:

  • python中强制显示(显胜于隐),形如C++中的this指针
  • 可以改成任意内容(推荐self)
  • self参数就代表了当前调用某个方法的对象
  • 只和对象有关,与类无关(代表实例,不代表类)

类方法

专门操作类变量的方法

@classmethod
def plus_sum(cls):
    pass

一、定义与调用:

  • 定义类方法:

    • @classmethod:装饰器
    • 关键字参数推荐为cls(class简写):代表当前类的参数
  • 调用类方法:

    类名.类方法         # 推荐
    对象名.类方法       # 不推荐
    

二、变量访问:

  • 访问类变量

          cls.类变量名  
    
  • 不能访问实例变量

三、一个栗子:

将前面实现学生总数统计(类变量的意义)的代码放到类方法中操作↓

class Student ():
    total=0 
    def __init__(self,n,a):
       self.name=n
       self.age=a
    @classmethod
    def plus_sum(cls):
        cls.total+=1  #类方法中调用类变量: cls.类变量名

stu1=Student("lisi",20)
Student.plus_sum()    # 调用类方法: 类名.类方法(推荐)
stu2=Student("liufang",21)
stu1.plus_sum()       # 调用类方法:对象名.类方法(不推荐)
print(Student.total)
2

静态方法

@staticmethod
def  add(x,y):
    pass
  • 定义与调用:
    • 无需传递指定的参数
    • 对象和类都可调用静态方法
  • 变量访问:
    • 静态方法内部可以访问类变量
    • 不能访问实例变量

成员可见性

设置私有数据

编程提倡规范:对于对类内数据成员的更改赋值,应调用相应的赋值方法,而不是类外直接访问赋值

class Student ():
    def __init__(self,n,a):
       self.name=n
       self.age=a
       self.score=0     # 初始状态
    def marking(self,s):   # 打分的函数
        if self.score<0:   #在函数中可以对输入的分数有限制
            print("分数不能小于0")
        else:
            self.score=s
stu1=Student("lisi",20)
stu1.marking(100)
# stu1.score=-1 不提倡直接访问赋值
print(stu1.score)
100

阻止别人在类外赋值:

python变量私有化:双下划线+变量名/方法名

__变量名
__方法名
class Student():
    def __init__(self,n,a):
        self.__name=n
        self.__age=a
    def __printer(self):
        print(self.__name)
stu1=Student("zhangsan",20)
print(stu1.__name)
stu1.__printer()
**报错**    # 因为无法访问方法和实例变量

双下划线+init+双下划线构造函数可以类外访问,因为当存在 双下划线+变量/方法名+双下划线 结构时,python认为可以访问

类外强制访问私有数据

进阶↓

class Student():
    def __init__(self,n,a):
        self.__name=n
        self.__age=a
        self.__score=60
    def __printer(self):
        print(self.__name)
stu1=Student("zhangsan",20)
stu1.__score=-1
print(stu1.__score)
-1

“事实”证明:类外不仅能对类内__score变量强制赋值还能强制访问??

解析!!!
并不是score私有化没有生效,而是因为python的动态性原因,而使stu1对象中新生成了变量"__score",而后对新的普通值进行了读取

print(stu1.__dict__)    # 输出stu1对象的字典检查其内部数据
-1
{'_Student__name': 'zhangsan', '_Student__age': 20, '_Student__score':60, '__score': -1}

输出的字典中,“zhangsan"是类私有成员,”__socre"是强行新定义的动态添加的变量。
python在检查到私有变量后会改变变量的名称:单下划线+类名+双下划线+变量名

_类名__变量名

这也是为什么在类外无法通过"__变量名"访问类的私有变量,因为名称已被python改变,输入原来变量名是无效的
因此
只要通过读取python改变的新的变量名就可以访问私有数据成员!!

print(stu1._Student__score)   # 访问新的名字
60

继承性

**作用:**避免定义重复的语法和重复的变量

形式:

class Human():
    def __init__(self,n,a):
        self.name=n
        self.age=a

from "模块" import Human
class Student(Human):
    def __init__(self,s,n,a):
        self.score=s
        super(Student,self).__init__(n,a)  #子类构造函数的继承
        # Human.__init__(self,n,a)

构造函数的继承

super(子类名,self).__init__(父类构造函数形参)

父类名.__init__(self,父类构造参数形参)

super关键字:

不仅可在子类构造函数中使用,也可在子类实例方法使用。

class Human():
    def __init__(self,n,a):
        self.name=n
        self.age=a
    def printer(self):
        print("this is parent class")

class Student(Human): 
    def __init__(self,s,n,a):
        self.score=s
        super(Student,self).__init__(n,a)  
    def printer(self):
        super(Student,self).printer()
        print("this is subclass")

stu1=Student(100,"zhangsan",18)
stu1.printer()
this is parent class
this is subclass

面向对象三大特性:

  • 继承性
  • 封装性
  • 多态性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值