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


参考

posted @ 2021-08-06 16:48  HUGBOY  阅读(196)  评论(0编辑  收藏  举报