Python类

1.python中使用a = a + a创建了一个新的变量a,覆盖了之前的变量a。而使用a += a 则是直接对原变量 a 进行操作
   https://www.cnblogs.com/hejianlong/p/9718637.html

2.类: 实例属性和类属性

 https://www.jianshu.com/p/85438fde74ca

实例属性

虽然我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性。例如,Person类应该在创建的时候就拥有 name、gender 和 birth 属性,怎么办?

在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

class Person(object):
    def __init__(self, name, gender, birth):
        self.name = name
        self.gender = gender
        self.birth = birth

__init__() 方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以自由指定,和定义函数没有任何区别。

相应地,创建实例时,就必须要提供除 self 以外的参数:

xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')

有了__init__()方法,每个Person实例在创建时,都会有 name、gender 和 birth 这3个属性,并且,被赋予不同的属性值,访问属性使用.操作符:

print xiaoming.name
# 输出 'Xiao Ming'
print xiaohong.birth
# 输出 '1992-2-2'

要特别注意的是,初学者定义__init__()方法常常忘记了 self 参数:

>>> class Person(object):
...     def __init__(name, gender, birth):
...         pass
... 
>>> xiaoming = Person('Xiao Ming', 'Male', '1990-1-1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 3 arguments (4 given)

这会导致创建失败或运行不正常,因为第一个参数name被Python解释器传入了实例的引用,从而导致整个方法的调用参数位置全部没有对上。

下面定义的Person类的__init__方法,除了接受 name、gender 和 birth 外,还可接受任意关键字参数,并把他们都作为属性赋值给实例。

class Person(object):
    def __init__(self,name,gender,birth,**kwargs):
        self.name = name
        self.gende = gender
        self.birth = birth
        for(key,value) in kwargs.iteritems():
            setattr(self, key, value)

setattr(self, key, value)用来设置属性,关键字参数实际上是字典


类属性

类是模板,而实例则是根据类创建的对象。

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

定义类属性可以直接在 class 中定义:

class Person(object):
    address = 'Earth'
    def __init__(self, name):
        self.name = name

因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问:

print Person.address
# => Earth

对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性:

p1 = Person('Bob')
p2 = Person('Alice')
print p1.address
# => Earth
print p2.address
# => Earth

由于Python是动态语言,类属性也是可以动态添加和修改的

Person.address = 'China'
print p1.address
# => 'China'
print p2.address
# => 'China'

因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了

下面的Person 类添加一个类属性 count,每创建一个实例,count 属性就加 1,这样就可以统计出一共创建了多少个 Person 的实例。

class Person(object):
    count = 0
    
    def __init__(self,name):
        self.name = name
        Person.count += 1
        

p1 = Person('Bob')
print Person.count

p2 = Person('Alice')
print Person.count

p3 = Person('Tim')
print Person.count

输出结果
1
2
3


python中类属性和实例属性名字冲突怎么办

修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?

class Person(object):
    address = 'Earth'
    def __init__(self, name):
        self.name = name

p1 = Person('Bob')
p2 = Person('Alice')

print 'Person.address = ' + Person.address

p1.address = 'China'
print 'p1.address = ' + p1.address

print 'Person.address = ' + Person.address
print 'p2.address = ' + p2.address

结果如下:

Person.address = Earth
p1.address = China
Person.address = Earth
p2.address = Earth

我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',但是,Person.address和p2.address仍然是'Earch',怎么回事?

原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:

访问 p1.address 时,优先查找实例属性,返回'China'。

访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。

可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

当我们把 p1 的 address 实例属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:

del p1.address
print p1.address
# => Earth

可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

把count改为私有__count,这样实例变量在外部无法修改__count:

class Person(object):

    __count = 0

    def __init__(self, name):
        self.name = name
        Person.__count += 1
        print(Person.__count)

p1 = Person('Bob')
p2 = Person('Alice')

try:
    print Person.__count #无法访问
except AttributeError:
    print('attributeerror')

类方法

和属性类似,方法也分实例方法和类方法。

在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。

要在class中定义类方法,需要这么写:

class Person(object):
    __count = 0
    def __init__(self,name):
        self.name = name
        Person.__count += 1 
    @classmethod
    def how_many(cls):
        return cls.__count


print Person.how_many()

p1 = Person('Bob')

print Person.how_many()

通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。

因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

对于私有属性__count,外部无法读取__count,但上面代码通过一个类方法how_many()获取。


实例属性通过self或实例变量来定义,注意__init__方法中定义的是实例属性 https://www.liaoxuefeng.com/wiki/1016959663602400/1017594591051072

关于类
class people:
内部函数 def __init__(self) / def __private(self) / def _protected(self) /def common(self)
类的专有方法__init__ __del__ __add__ __sub__ __repr__ __str__
类的特殊类属性 function.__dict__ 说出类的属性
内部变量 类属性是定义在类内函数之外的 就一个 无论申请几个对象 大家一起用 在函数内用的话
self.name self.__age self._pri
实例属性通过实例变量和self定义

继承:
class student(people,cat):
def __init__(self,n,a,w,g):
people.__init__(self,n,a,w)
cat.__init__(self,n,g)

https://blog.csdn.net/weixin_42233629/article/details/82256324 __str__ __repr__()

制表符:
t取的是table之意。它的含义是一个字符,叫做制表符。它的作用是对齐表格数据的各列。
#换行符和制表符的写法只有在引号内才起作用,才会被视为一个字符
#制表符的写法是 ,作用是对齐表格的各列。
print("学号 姓名 语文 数学 英语")
print("2017001 曹操 99 88 90")
print("2017002 周瑜 92 45 93")
print("2017008 黄盖 77 82 100")
'''
学号 姓名 语文 数学 英语
2017001 曹操 99 88 90
2017002 周瑜 92 45 93
2017008 黄盖 77 82 100
'''
print("I'm Bob, what is your name?")
#I'm Bob, what is your name?中间4个空格

原文地址:https://www.cnblogs.com/yundong333/p/11104221.html