python 区别_在Python中,与,python,和,xx,的,区别

0 前言

python灵活的语法,给我们带了一些便利,同时也给我们带了一些困惑。其中就是我们常见的_、__和__xx__的作用和区别,这节我们就来看一下。

1 理论

Python中不存在真正的私有方法。为了实现类似于c++中私有方法,可以在类的方法或属性前加一个“_”单下划线,意味着该方法或属性不应该去调用,它并不属于API。但是,

这只是一个形式上的约定,python并不阻止调用。

__双下划线的作用是避免覆盖其内容,实现的机制是在带有双下划线的方法或属性前加上_类名的标识。由于,

python自动对方法和属性进行了改写,所以直接调用带有双下划线的方法是调用不到的。

xx

”经常是操作符或本地函数调用的magic methods。在上面的例子中,提供了一种重写类的操作符的功能。

它是用于Python调用的。

2 例子

首先定义两个类:

class Student(object):

def __init__(self, name, age):

self.name = name

self.age = age

def _getname(self): #单下划线

print('返回名字')

return self.name

def __getage(self): #双下划线

print('Stuent:返回年龄')

return self.age

def __str__(self):

return '{}:{}'.format(self.name, self.age)

class UnderStudent(Student):

def __init__(self, name, age, university):

super(UnderStudent,self).__init__(name, age)

self.university = university

def __getage(self):

print('UnderStudent:返回年龄')

return self.age

def __str__(self):

return '{}:{}:{}'.format(self.name, self.age, self.university)

93c66b57a0384b391aaf308aa1447ed6.png

可以看到带有单下划线的方法,可以在类外直接调用,这说明它不是真正的私有方法,只是一个约定。

带有双下划线的方法,直接调用会提示找不到该方法。我们使用dir函数来显示类所有的属性看看。

print(dir(Student))

print(dir(UnderStudent))

['_Student__getage', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_getname']

['_Student__getage', '_UnderStudent__getage', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_getname']

通过输出内容可以看到,在Student类中__getage被改写为_Student__getage,UnderStudent继承了_Student__getage。由于我们在UnderStudent中也定义了__getage,他被改写为_UnderStudent__getage,

避免了对父类Student__getage的覆盖。

可见双下划线的方法在类外是不能调用的,因为它的名字已经被改变。

既然知道改写后的方法名,我们就可以直接使用改写后的方法名进行调用了。

if __name__ == '__main__':

s = Student('张三', 20)

print(s)

print(s._getname())

# print(s.__getage())

print(s._Student__getage())

print('------------------------------------')

us = UnderStudent('李四', 22, '哈工大')

print(us)

print(us._getname())

# print(us.__getage())

print(us._Student__getage())

print(us._UnderStudent__getage())

77a72f2acf9661912f0fe998e31b48e9.png

既然双下划线的属性在外部不能调用,那么这种方法有什么用呢?

作用是,这种方法可以在类内部被调用,并且不能被子类的方法覆盖。

我们为Student类,添加message属性

class Student(object):

def __init__(self, name, age):

self.name = name

self.age = age

def _getname(self):

print('返回名字')

return self.name

def __getage(self):

return 'Student:{}'.format(self.age)

def message(self):

print('In Student')

return self.__getage()

def __str__(self):

return '{}:{}'.format(self.name, self.age)

class UnderStudent(Student):

def __init__(self, name, age, university):

super(UnderStudent,self).__init__(name, age)

self.university = university

def __getage(self):

return 'UnderStudent:'.format(self.age)

def __str__(self):

return '{}:{}:{}'.format(self.name, self.age, self.university)

if __name__ == '__main__':

s = Student('张三', 20)

print(s)

print(s._getname())

print(s.message())

print('------------------------------------')

us = UnderStudent('李四',22,'哈工大')

print(us)

print(us._getname())

print(us.message())

5de4c5a32b5e1b97529f2a773eb9fa94.png

在method方法中调用了__getage,虽然在UnderStudent对__getage方法进行了改写,但是us对象调用的仍然是Student的__getage方法。

下面再来看,如果在UnderStudent也添加message方法呢?

class Student(object):

def __init__(self, name, age):

self.name = name

self.age = age

def _getname(self):

print('返回名字')

return self.name

def __getage(self):

return 'Student:{}'.format(self.age)

def message(self):

print('In Student')

return self.__getage()

def __str__(self):

return '{}:{}'.format(self.name, self.age)

class UnderStudent(Student):

def __init__(self, name, age, university):

super(UnderStudent,self).__init__(name, age)

self.university = university

def __getage(self):

return 'UnderStudent:{}'.format(self.age)

def message(self):

print('In UnderStudent')

return self.__getage()

def __str__(self):

return '{}:{}:{}'.format(self.name, self.age, self.university)

if __name__ == '__main__':

s = Student('张三', 20)

print(s)

print(s._getname())

print(s.message())

print('------------------------------------')

us = UnderStudent('李四',22,'哈工大')

print(us)

print(us._getname())

print(us.message())

0b275147c6aec69e8738ce52c88f4c40.png

这时候us调用message,message调用的就是UnderStudent的__getage方法了。

下面再看一个关于__xx__方法的例子:

class CrazyNumber(object):

def __init__(self, n):

self.n = n

def __add__(self, other):

return self.n - other

def __sub__(self, other):

return self.n + other

def __str__(self):

return str(self.n)

num = CrazyNumber(10)

print num # 10

print num + 5 # 5

print num - 20 # 30

这个很好理解就不解释了。

总结

单下划线,形式上约定为私有方法,单python并不阻止调用。

__双下划线的作用是避免覆盖其内容,实现的机制是在带有双下划线的方法或属性前加上_类名的标识。

xx

”用于Python调用的操作符或本地函数调用的magic methods。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值