python面向对象(属性,方法)

python面向对象1

面向对象(属性,方法)

类的定义

  • 关键字class

  • 格式class 类名

    class MyClass:
        pass
    

类的内部和外部

  • 类的内部:从类的定义class开始,到类的定义结束,这个范围内都称为类的内部。
  • 除类定义的范围外的所有位置都叫类的外部,即使是同一个py文件中也是类的外部。

属性

类属性

公有类属性
  • 定义在类中,定义在方法外,不使用双下划线__打头的变量。
    • 在类内部的方法中使用时 self.public_attr
    • 在类外,可以使用类名.public_attr或者实例名.public_attr访问
class MyClass:
    public_para = 10 #公有变量,类外可以方法
私有类属性
  • 两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。
    • 在类内部的方法中使用时 self.private_attrs
    • 在类外不可以访问
class MyClass:
    __private_para = 100 #私有变量,类外不可以访问
举例
class MyClass:
    public_para = 10 #公有属性

    def fun(self):
        self.public_para += 1

obj1 = MyClass()
obj2 = MyClass()

pub_para_res1_by_className1 = MyClass.public_para #类外可以访问,使用 类名.公有属性名 10
MyClass.public_para += 5 #通过类名访问公有属性,并对其重新赋值,则类的公有属性被新的值覆盖 15

pub_para_res1_by_obj1 = obj1.public_para #类外可以方法,使用 对象名.公有属性名 15
obj1.public_para += 5 #通过对象名访问公有属性,并对其重新赋值,则只会修改该对象中的 public_para

pub_para_res1_by_obj2 = obj2.public_para #类外可以方法,使用 对象名.公有属性名 15

print('pub_para_res1_by_className1:%s' % pub_para_res1_by_className1) #10+5 → 15
print('pub_para_res1_by_obj1:%s' % pub_para_res1_by_obj1) #15+5 → 20
print('pub_para_res1_by_obj2:%s' % pub_para_res1_by_obj2) #15

obj1.fun() #修改自身的public_para,20+1→21
obj2.fun() #修改自身的public_para,15+1→16

pub_para_res2_by_className2 = MyClass.public_para #类外可以访问,使用 类名.公有属性名 15
pub_para_res2_by_obj1 = obj1.public_para #类外可以访问,使用 对象名.公有属性名 21
pub_para_res2_by_obj2 = obj2.public_para #类外可以访问,使用 对象名.公有属性名 16
print('pub_para_res2_by_className2:%s' % pub_para_res2_by_className2)
print('pub_para_res2_by_obj1:%s' % pub_para_res2_by_obj1)
print('pub_para_res2_by_obj2:%s' % pub_para_res2_by_obj2)

# 结果
pub_para_res1_by_className1:10
pub_para_res1_by_obj1:15
pub_para_res1_by_obj2:15
pub_para_res2_by_className2:15
pub_para_res2_by_obj1:21
pub_para_res2_by_obj2:16
class MyClass:
    __private_para = 10 #公有属性

    def fun(self):
        self.__private_para += 1

    def fun_ret(self):
        return self.__private_para

obj1 = MyClass()
obj2 = MyClass()

obj1.fun()
obj2.fun()
obj2.fun()

pri_res1 = obj1.fun_ret()
pri_res2 = obj2.fun_ret()

print(pri_res1)
print(pri_res2)

# 结果
11
12
class MyClass:
    __private_para = 10 #公有属性

    def fun(self):
        self.__private_para += 1

    def fun_ret(self):
        return self.__private_para

obj = MyClass()

prv_res_byObjName = obj.__private_para #试图从类的外部,访问私有类属性,会抛异常
prv_res_byClassName = MyClass.__private_para #试图从类的外部,访问私有类属性,会抛异常

# 结果
AttributeError: 'MyClass' object has no attribute '__private_para'
小结
  • 类属性的访问
    • 在类内,无论是公有属性还是私有属性,总是可以通过类名或者通过对象名访问
    • 在类外,公有属性可以通过类名或者通过对象名访问;私有属性都不可以访问
  • 类属性的修改
    • 通过类名修改后的类属性,会更新类属性的值。
    • 通过对象名修改的类属性,只会更新属于对象本身中的类属性,其值的修改不会影响通过类获取的类属性的值。
      • 通过对象名最开始获取的类属性对象名.类属性总得到先从类的类属性最新值
  • 在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。

实例属性

  • 每个实例都可以有自己的变量用来保存对象自己的数据,称为实例变量(也叫属性)

  • 给实例绑定属性的方法是通过实例变量,或者通过self变量

  • 定义和访问的方式

    • 定义self.实例属性=值
    • 访问self.实例属性
    • 赋值规则同变量的赋值规则
      • 首次为属性赋值,则创建此属性
      • 再次为属性赋值,则改变此属性的绑定关系
非私有实例属性
class MyClass:

    def __init__(self, objAttrPara):
        self.objAttr = objAttrPara #这里的self.objAttr为实例属性,为当前调用者所有。
                                   #通过self.objAttr进行访问

    def fun(self):
        self.objAttr += 1 #通过 对象名.实例属性 在类内访问并修改

    def funRet(self):
        return self.objAttr

obj1 = MyClass(30)
obj2 = MyClass(3)

print('通过对象名obj直接访问的方式获得实例obj1属性:%s' % obj1.objAttr)#通过 对象名.实例属性 访问

print('-'*40)
obj1.fun()
obj2.fun()
obj2.fun()
obj2.objAttr +=3 #通过 对象名.实例属性 在类外访问并修改

print('通过对象名obj1直接访问的方式获得实例obj1属性:%s' % obj1.funRet())
print('通过对象名obj1直接访问的方式获得实例obj1属性:%s' % obj2.objAttr)

# 结果
通过对象名obj直接访问的方式获得实例obj1属性:30
----------------------------------------
通过对象名obj1直接访问的方式获得实例obj1属性:31
通过对象名obj1直接访问的方式获得实例obj1属性:8
私有实例属性
class MyClass:

    def __init__(self, objAttrPara):
        self.__objAttr = objAttrPara #这里的self.objAttr为实例属性,为当前调用者所有。
                                    #在类内通过self.objAttr进行访问
                                    #在类外无法通过self.objAttr进行访问

    def fun(self):
        self.__objAttr += 1 #通过 对象名.实例属性 在类内访问并修改

    def funRet(self):
        return self.__objAttr
    

obj = MyClass(30)

obj.fun()
print('通过对象名obj直接访问的方式获得实例obj1属性:%s' % obj.funRet())

print('通过对象名obj直接访问的方式获得实例obj1属性:%s' % obj.__objAttr)#通过 对象名.私有实例属性 访问,会报异常

# 结果
通过对象名obj直接访问的方式获得实例obj1属性:31
  File "G:/testSele.py", line 18, in <module>
    print('通过对象名obj直接访问的方式获得实例obj1属性:%s' % obj.__objAttr)#通过 对象名.实例属性 访问
AttributeError: 'MyClass' object has no attribute '__objAttr'

方法

类方法

  • 使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是当前实例。
    • self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。
一般方法
  • 调用方式

    • 在类内通过self.方法名(实参列表)调用

    • 在类外用通过对象名.方法名(实参列表)调用

class MyClass:

    def generalMethod(self, para): #定义一个一般方法
        print('这是一个一般方法')
        print('传入的para参数为:%s' % para)


    def callGenMethod(self):
        print('内部调用一般方法')
        self.generalMethod(100)


obj = MyClass()
obj.generalMethod(10) #在外部通过 对象名.方法名(实参列表) 调用
obj.callGenMethod()

# 结果
这是一个一般方法
传入的para参数为:10
内部调用一般方法
这是一个一般方法
传入的para参数为:100
私有方法
  • 个下划线开头的方法,声明该方法为私有方法。def __privateMethod(参数列表)
  • 调用方式
    • 在类的内部通过self.私有函数名(实参列表)调用
    • 在类的外部库可以调用
class MyClass:

    def __privatelMethod(self, para): #定义一个一般方法
        print('这是一个私有方法')
        print('传入的para参数为:%s' % para)


    def callGenMethod(self):
        print('内部调用私有方法')
        self.__privatelMethod(100) #在类内部通过 self.__privateMethod(实参列表) 调用


obj = MyClass()
obj.callGenMethod() 
obj.__privateMethod # 在类外调用私有方法,会抛异常

# 结果
内部调用私有方法
Traceback (most recent call last):
这是一个私有方法
传入的para参数为:100
  File "G:/testSele.py", line 15, in <module>
    obj.__privateMethod
AttributeError: 'MyClass' object has no attribute '__privateMethod'

类专有方法

  • 以双下划线开始且以双下划线结尾的方法为类的专用方法,__变量__。这样的专有方法个数有限,有各自的特殊作用。
  • 有些__变量__不是类专有方法,而是一些特殊变量。如__name____main__
专有方法举例
_init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
 
__call__: 函数调用

__cmp__: 比较运算
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__truediv__: 除运算
__mod__: 求余运算
__pow__: 乘方
            
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
        
__len__: 获得长度
运算符重载
  • 需要借用类专有方法才能实现
class MyClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):#自定义用于打印的字符串数据
        return '使用__str__返回的字符串值为:(%d, %d)' % (self.a, self.b)

    def __add__(self, otherObj): #重载 加法+ 运算符,
                                 #其中otherObj为加法后面的同属于MyClass类型的对象
        return MyClass(self.a + otherObj.a, self.b + otherObj.b)

v1 = MyClass(2, 10)
v2 = MyClass(5, -12)
v3 = v1 + v2
print(v3)

# 结果
使用__str__返回的字符串值为:(7, -2)

Python中的下划线

  • 前后没有下划线的是公有方法或属性
  • 前边有一个下划线的为私有方法或属性,子类无法继承
  • 前边有两个下划线的 一般是为了避免于子类属性或者方法名冲突,无法在外部直接访问
  • 前后都有双下划线的为系统方法或属性
  • 后边单个下划线的可以避免与系统关键词冲突
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值