Python用法速查@类
类和实例
class Animal(object):...
所有的类最终都继承自object类。
类是具有相同方法和属性的一组对象的集合。
class Animal(object):
pass
animal = Animal()
>>> animal = Animal() # 创建一个实例对象
>>> animal
<__main__.Animal at 0x1030a44d0>
animal = Animal(args)
>>> animal = Animal('dog1') # 传入参数 'dog1'
>>> animal.name # 访问对象的 name 属性
'dog1'
def __init__(self, name):...
class Animal(object):
def __init__(self, name): #初始化方法
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
dog1.greet()
>>> dog1 = Animal('dog1')
>>> dog1.name
'dog1'
>>> dog1.greet()
Hello, I am dog1.
self.__name=name
访问控制
_a
表示不要随意访问这个变量,虽然可以直接访问
__name
外部不可直接访问
__name__
特殊变量,可直接访问
class Animal(object):
def __init__(self, name):
self.__name = name
def greet(self):
print 'Hello, I am %s.' % self.__name
----------------------------
>>> dog1 = Animal('dog1')
>>> dog1.__name # 访问不了
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-206-7f6730db631e> in <module>()
----> 1 dog1.__name
AttributeError: 'Animal' object has no attribute '__name'
>>> dog1.greet() # 可以访问
Hello, I am dog1.
获取对象信息
type(obj)
isinstance(obj, class)
>>> dog1 = Animal('dog1')
>>> type(dog1) #获取对象类型
__main__.Animal
>>> isinstance(dog1, Animal)#对象是否为对应类型
True
hasattr(obj, attr)
getattr(obj, attr[, default])
setattr(obj, attr, value)
>>> hasattr(dog1, 'name')#对象是否有对应属性
True
>>> hasattr(dog1, 'x')
False
>>> hasattr(dog1, 'greet')#对象是否有对应方法
True
>>> getattr(dog1, 'name')#获取属性值
'dog1'
>>> getattr(dog1, 'greet')#获取方法
<bound method Animal.greet of <__main__.Animal object at 0x10c3564d0>>
>>> getattr(dog1, 'x')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-241-42f5b7da1012> in <module>()
----> 1 getattr(dog1, 'x')
AttributeError: 'Animal' object has no attribute 'x'
>>> getattr(dog1, 'x', 'xvalue')#没有该属性时默认返回xvalue
'xvalue'
>>> setattr(dog1, 'age', 12)#设置属性值
>>> dog1.age
12
dir(obj)
#获取所有 方法名和属性 列表
>>> dir(dog1)
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'age',
'greet',
'name']
继承
class Dog(Animal):
子类可以在父类基础上覆盖和添加方法
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
#结果
>>> animal = Animal('animal') # 创建 animal 实例
>>> animal.greet()
Hello, I am animal.
>>>
>>> dog = Dog('dog') # 创建 dog 实例
>>> dog.greet()
WangWang.., I am dog.
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
def run(self):
print 'I am running.I am running'
#结果
>>> dog = Dog('dog')
>>> dog.greet()
WangWang.., I am dog.
>>> dog.run()
I am running
多态
obj.method()
多态不同的对象对同一消息作出不同的响应
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s.' % self.name
class Cat(Animal):
def greet(self):
print 'MiaoMiao.., I am %s' % self.name
def hello(animal):
animal.greet()
#结果
>>> dog = Dog('dog')
>>> hello(dog)
WangWang.., I am dog.
>>>
>>> cat = Cat('cat')
>>> hello(cat)
MiaoMiao.., I am cat
类方法
@classmethod=>cls.method()
上面都是通过实例来调用方法,Python 提供了@classmethod
装饰器让我们也可以用类调用方法。
class A(object):
bar = 1
@classmethod
def class_foo(cls): #参数cls是class A(object):类本身
print 'Hello, ', cls
print cls.bar #我们可以直接调用类的方法
>>> A.class_foo() # 直接通过类来调用方法
Hello, <class '__main__.A'>
1
静态方法
@staticmethod=>cls.method()
某些不改变类和实例状态,但又和类有关系的方法。我们用@staticmethod
来装饰。
class A(object):
bar = 1
@staticmethod
def static_foo(): #静态方法无cls参数,可以写到类外面,但这将不利于 代码的组织 和 命名空间的整洁
print 'Hello, ', A.bar
>>> a = A()
>>> a.static_foo()
Hello, 1
>>> A.static_foo()
Hello, 1
定制类和魔法方法
常见魔法方法(特殊方法)
__new__
__str__ , __repr__
__iter__
__getitem__ , __setitem__ , __delitem__
__getattr__ , __setattr__ , __delattr__
__call__
def __new__(cls):...=>obj=Class()
def __init__(self):...
__new__
在__init__
之前执行,我们可用此方法控制实例的创建过程。
class A(object):
_dict = dict()
def __new__(cls): # 类方法
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return object.__new__(cls)
def __init__(self): # 实例方法
print "INIT"
A._dict['key'] = self
# 结果
>>> a1 = A()
NEW
INIT
>>> a2 = A()
EXISTS
INIT
>>> a3 = A()
EXISTS
INIT
def __str__(self):...=>print(obj)
__str__
可用于备注类的详细信息
class Foo(object):
def __init__(self, name):
self.name = name
def __str__(self): # 在打印对象时自动调用
return 'Foo object (name: %s)' % self.name
>>> print Foo('ethan') # 使用 print
Foo object (name: ethan)
>>>
>>> str(Foo('ethan')) # 使用 str
'Foo object (name: ethan)'
>>>
>>> Foo('ethan') # 直接显示
<__main__.Foo at 0x10c37a490>
def __repr__(self):...=>obj()
上面直接显示
时还是默认信息,如果我们想让直接显示的也是备注的详细信息
class Foo(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Foo object (name: %s)' % self.name
def __repr__(self):
return 'Foo object (name: %s)' % self.name
>>> Foo('ethan')
'Foo object (name: ethan)'
或
class Foo(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Foo object (name: %s)' % self.name
__repr__ = __str__
def __iter__(self):...=>for i in obj:...
def __next__(self):...
让实例可用于for循环
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self): # 返回迭代器对象本身
return self
def next(self): # 返回容器下一个元素
self.a, self.b = self.b, self.a + self.b
return self.a
>>> fib = Fib()
>>> for i in fib:
... if i > 10:
... break
... print i
...
1
1
2
3
5
8
# -*- coding: utf-8 -*-
# @Time : 2021/6/18 21:33
# @Author : HUGBOY
# @File : HelloYoutube.py
# @Software: PyCharm
class fiber(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
f = fiber()
for i in f:
print(i, end="~")
if i >= 100:
break
# 结果
D:\python\python.exe E:/PYTHON/Basics/Fun/HelloYoutube.py
1~1~2~3~5~8~13~21~34~55~89~144~
Process finished with exit code 0
def __getitem__(self):...=>obj[n]/obj[a:b]
实现用obj[n]方法来获取实例的值,如fiber数列。
class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in xrange(n):
a, b = b, a + b
return a
>>> fib = Fib()
>>> fib[0], fib[1], fib[2], fib[3], fib[4], fib[5]
(1, 1, 2, 3, 5, 8)
# -*- coding: utf-8 -*-
# @Time : 2021/6/18 21:33
# @Author : HUGBOY
# @File : HelloYoutube.py
# @Software: PyCharm
class fiber(object):
def __getitem__(self, n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
itemf = fiber()
print(itemf[0], itemf[6], itemf[10])
#结果
D:\python\python.exe E:/PYTHON/Basics/Fun/HelloYoutube.py
0 8 55
Process finished with exit code 0
在上面的基础上实现分片slics
# -*- coding: utf-8 -*-
# @Time : 2021/6/18 21:33
# @Author : HUGBOY
# @File : HelloYoutube.py
# @Software: PyCharm
class sFiber():
def __getitem__(self, n):
if isinstance(n, int): #判断参数n是否为 int 类型
a, b = 0, 1
for i in range(n+1):
a, b = b, a + b
if i == n:
return a
if isinstance(n, slice):#判断参数n是否为 slice对象 类型
a, b = 0, 1
start, stop = n.start, n.stop
lis = []
for i in range(stop+1):
a, b = b, a + b
if i >= start:
lis.append(a)
return lis
sf = sFiber()
print(sf[2:9], sf[2], sf[9])
# 结果
D:\python\python.exe E:/PYTHON/Basics/Fun/HelloYoutube.py
[2, 3, 5, 8, 13, 21, 34, 55] 2 55
Process finished with exit code 0
def __setitem__(self):...=>obj['key']=value/len(obj)
def __delitem__(self):...=>del obj['key']
类似def __getitem__(self):...
获取值,它们分别用于设置值,删除值
class Point(object):
def __init__(self):
self.coordinate = {}
def __str__(self):
return "point(%s)" % self.coordinate
def __getitem__(self, key):
return self.coordinate.get(key)
def __setitem__(self, key, value):
self.coordinate[key] = value
def __delitem__(self, key):
del self.coordinate[key]
print 'delete %s' % key
def __len__(self):
return len(self.coordinate)
__repr__ = __str__
# 结果
>>> p = Point()
>>> p['x'] = 2 # 对应于 p.__setitem__('x', 2)
>>> p['y'] = 5 # 对应于 p.__setitem__('y', 5)
>>> p # 对应于 __repr__
point({'y': 5, 'x': 2})
>>> len(p) # 对应于 p.__len__
2
>>> p['x'] # 对应于 p.__getitem__('x')
2
>>> p['y'] # 对应于 p.__getitem__('y')
5
>>> del p['x'] # 对应于 p.__delitem__('x')
delete x
>>> p
point({'y': 5})
>>> len(p)
1
def __getattr__(self):...=>obj.x
当我们获取某个属性不存在时,会报错
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
>>> p = Point(3, 4)
>>> p.x, p.y
(3, 4)
>>> p.z
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-547-6dce4e43e15c> in <module>()
----> 1 p.z
AttributeError: 'Point' object has no attribute 'z'
用__getattr__
方法防止报错
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __getattr__(self, attr):
if attr == 'z':#访问z,返回0,如果访问其他的如w会默认返回None
return 0
>>> p = Point(3, 4)
>>> p.z
0
还可以加入异常处理
def __getattr__(self, attr):
if attr == 'z':
return 0
raise AttributeError("Point object has no attribute %s" % attr)
def __setattr__(self):...=>obj.x=value
def __delattr__(self):...=>del obj.x
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __getattr__(self, attr):
if attr == 'z':
return 0
raise AttributeError("Point object has no attribute %s" % attr)
def __setattr__(self, *args, **kwargs):
print 'call func set attr (%s, %s)' % (args, kwargs)
return object.__setattr__(self, *args, **kwargs)
def __delattr__(self, *args, **kwargs):
print 'call func del attr (%s, %s)' % (args, kwargs)
return object.__delattr__(self, *args, **kwargs)
>>> p = Point(3, 4)
call func set attr (('x', 3), {})
call func set attr (('y', 4), {})
>>> p.z
0
>>> p.z = 7
call func set attr (('z', 7), {})
>>> p.z
7
>>> p.w
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: Point object has no attribute w
>>> p.w = 8
call func set attr (('w', 8), {})
>>> p.w
8
>>> del p.w
call func del attr (('w',), {})
>>> p.__dict__
{'y': 4, 'x': 3, 'z': 7}
def __call__(self):...=>callable(obj)
一般用obj.method()调用对象,我们也可以用callable()直接在实例本身上调用
class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
def __call__(self, z):
return self.x + self.y + z
# 结果
>>> p = Point(3, 4)
>>> callable(p) # 使用 callable 判断对象是否能被调用
True
>>> p(6) # 传入参数,对实例进行调用,对应 p.__call__(6)
13 # 3+4+6
slots 魔法
obj.new_x=value
给实例绑定新的属性和方法
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
>>> p = Point(3, 4)
>>> p.z = 5 # 绑定了一个新的属性
>>> p.z
5
>>> p.__dict__
{'x': 3, 'y': 4, 'z': 5}
def __slots__(self):...=>obj.some_x=value
限制绑定的属性
class Point(object):
__slots__ = ('x', 'y') # 只允许使用 x 和 y
def __init__(self, x=0, y=0):
self.x = x
self.y = y
>>> p = Point(3, 4)
>>> p.z = 5
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-648-625ed954d865> in <module>()
----> 1 p.z = 5
AttributeError: 'Point' object has no attribute 'z'
注意:子类只有使用slots魔法后才会继承父类的slots元组,组成tuple=child_slots_tuple+father_slots_tuple
@property=>obj.method
@method.setter=>obj.method=value
被@property装饰器,装饰过的方法
可以当做属性来用
class Exam(object):
def __init__(self, score):
self._score = score
@property
def score(self):
return self._score
@score.setter
def score(self, val):
if val < 0:
self._score = 0
elif val > 100:
self._score = 100
else:
self._score = val
>>> e = Exam(60)
>>> e.score
60
>>> e.score = 90
>>> e.score
90
>>> e.score = 200
>>> e.score
100
也可以不用@score.setter赋值装饰器
class Exam(object):
def __init__(self, score):
self._score = score
@property
def score(self):
return self._score
>>> e = Exam(60)
>>> e.score
60
>>> e.score = 200 # score 是只读属性,不能设置值
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-676-b0515304f6e0> in <module>()
----> 1 e.score = 200
AttributeError: can't set attribute
参考
________________________________________________________
Every good deed you do will someday come back to you.
Love you,love word !