In [1]:
# 多行结果输出支持
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
In [2]:
_formats = {
'ymd' : '{d.year}-{d.month}-{d.day}',
'mdy' : '{d.month}/{d.day}/{d.year}',
'dmy' : '{d.day}/{d.month}/{d.year}'
}
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __format__(self, code):
if code == '':
code = 'ymd'
fmt = _formats[code]
return fmt.format(d=self)
In [5]:
d = Date(2012, 12, 21)
d
format(d)
format(d, 'mdy')
'The date is {:ymd}'.format(d)
'The date is {:mdy}'.format(d)
Out[5]:
Out[5]:
Out[5]:
Out[5]:
Out[5]:
_
开头的名字都应该是内部实现(私有的)(__)
开头的命名表示private,会被重新命名
有时候你定义的一个变量和某个保留关键字冲突,这时候可以使用单下划线作为后缀
In [26]:
class A:
def __init__(self):
self._internal = 0 # An internal attribute
self.public = 1 # A public attribute
# @classmethod
def public_method(self):
'''
A public method
'''
print(2)
def _internal_method(self):
print(3)
In [27]:
a = A()
a.public
# Python不会阻止对内部属性或者方法的访问,但是并不建议这么做
a._internal
a.public_method()
a._internal_method()
Out[27]:
Out[27]:
In [28]:
class B:
def __init__(self):
self.__private = 0
def __private_method(self):
pass
def public_method(self):
pass
self.__private_method()
使用双下划线开始会导致访问名称变成其他形式。 比如,在前面的类B中,私有属性会被分别重命名为 _B__private
和 _B__private_method
。 这时候你可能会问这样重命名的目的是什么,答案就是继承——这种属性通过继承是无法被覆盖的
In [29]:
class C(B):
def __init__(self):
super().__init__()
self.__private = 1 # Does not override B.__private
# Does not override B.__private_method()
def __private_method(self):
pass
这里,私有名称 __private
和 __private_method
被重命名为 _C__private
和 _C__private_method
,这个跟父类B中的名称是完全不同的
In [31]:
# 为了避免关键字之间的冲突问题
lambda_ = 2.0 # Trailing _ to avoid clash with lambda keyword
In [35]:
class Person:
def __init__(self, first_name):
self.first_name = first_name
# Getter function
@property
def first_name(self):
return self._first_name
# Setter function
@first_name.setter
def first_name(self, value):
if not isinstance(value, str):
raise TypeError('Expected a string')
self._first_name = value
# Deleter function (optional)
@first_name.deleter
def first_name(self):
raise AttributeError("Can't delete attribute")
In [36]:
a = Person('autuanliu')
a.first_name
Out[36]:
In [40]:
# 设置的时候会执行一个类型检查的方法
a.first_name = 43
In [41]:
a.first_name = "autuan"
In [42]:
del a.first_name
In [43]:
import math
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * self.radius ** 2
@property
def diameter(self):
return self.radius * 2
@property
def perimeter(self):
return 2 * math.pi * self.radius
In [48]:
# 实例化一个圆的对象
xy = Circle(5.2)
In [51]:
# 可以直接通过属性的方式进行访问
xy.area
xy.diameter
xy.perimeter
Out[51]:
Out[51]:
Out[51]:
In [53]:
class A:
def spam(self):
print('A.spam')
class B(A):
def spam(self):
print('B.spam')
super().spam()
In [54]:
b = B()
In [55]:
b.spam()
In [60]:
class A:
def __init__(self):
self.x = 0
class B(A):
def __init__(self):
super().__init__()
self.y = 1
In [61]:
b = B()
b.x
b.y
Out[61]:
Out[61]:
In [65]:
from abc import ABCMeta, abstractmethod
# 抽象类
class IStream(metaclass=ABCMeta):
@abstractmethod
def read(self, maxbytes=-1):
pass
@abstractmethod
def write(self, data):
pass
In [66]:
# 抽象类不能直接被实例化
a = IStream()
In [67]:
class ss(IStream):
def read(self, maxbytes=-1):
print('read')
def write(self, data):
print('write')
In [69]:
aa = ss()
aa.read()
aa.write(data=1)
In [71]:
# @abstractmethod 还能注解静态方法、类方法和 properties 。 你只需保证这个注解紧靠在函数定义前即可
class A(metaclass=ABCMeta):
@property
@abstractmethod
def name(self):
pass
@name.setter
@abstractmethod
def name(self, value):
pass
@classmethod
@abstractmethod
def method1(cls):
pass
@staticmethod
@abstractmethod
def method2():
pass
In [73]:
# 静态方法实例
import math
class Circle1:
def __init__(self, radius):
self.radius = radius
@staticmethod
def area(self):
return math.pi * self.radius ** 2
In [79]:
aaa = Circle1(3)
Circle1.area(aaa)
Out[79]:
In [ ]: