24.python中类的方法
类中的方法,其实就是类中的函数,可以分为:实例方法,类方法,静态方法。方法和字段一样,也是属于类的属性,所以也具有运行中修改的特效, 但一般不推荐这样做。
我在类的基本语法中,介绍了构造器方法:__init__ 、__new__;解构器方法:__del__;
注意,这里虽然是以两个下划线(__)开头,但同时以两个下划线(__)结尾,这里表明其是一个‘魔法方法’,关于类中的魔法方法,将起一篇进行说明。
但是,如果单纯只以两个下划线开始,则依然是私有化的意思,看代码示例:
class Test(object): def __scolia__(self): # 一个类似魔术方法,并不是私有化
return 'scolia' def __good(self): # 私有方法
return 'good' a = Test()
print a.__scolia__() # 魔法方法可以在直接访问
print a.__good() # 私有方法不能直接访问
aaarticlea/png;base64,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" alt="" />
同样的,和字段私有化一样,我们也可能同特殊手段进行强制访问:
print a._Test__good() # 强制访问
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOcAAAAYCAIAAACOUn27AAAAzklEQVR4nO3a2wmEMBBG4SlrKppy0k2qSTH6sBrZjUQXEvSH870o4uXlMAbRloeYmZk99XRIoxvooVrooVrooVroGVttSW5mkYfeFPgxfNbmoFpMRrXQQ7XQc1ZtDjtEXvb1qnkq+zntkc9V7k61mKyttg7LulOSeyrH9uII1WKyk1m7jdFjkLYd39kBZunM2uqfWZuDL1+Y7WJduwV4f10bEXyxxWT9WcvrHm/UW9d+z1LgLfgPAXqoFnqoFnqoFnqoFnqoFnqoFnqoFnpW200MUgjCPoIAAAAASUVORK5CYII=" alt="" />
当然,私有方法也可以在类的内部访问,和私有字段一样。
所以说,属性的私有化都是对访问入口进行混淆,同样的,也不建议强制访问私有属性。
也许这里的‘魔法方法’看起来并不‘魔法’,详情将以后解释。
实例方法:
在 __init__ 构造器中,提起过其是一个实例方法,实例方法的特点就是:
1.方法的第一个参数必须是 self,当然这是约定俗成的写法,你可以将 self 换成 abc 之类的,但是为了别的程序员能看得懂,还是统一用 self 吧。这里的 self 代表实例本身,也就是说如果我实例化时使用的是: a = Test() ,那么 self 就代表 a 这个实例,我们可以在很多构造器中看到类似 self.scolia = 'good' 的写法,其实这个写法和在类外面 a.scolia = 'good' 效果一样,是为了添加属性,只不过 __init__ 方法是实例化时自动调用的函数,所以适合进行初始属性的创建。
2.实例方法在调用的时候,self 是自动传递的,所以不需要我们再处理。
3.实例方法一般要有实例才能调用,当然也有特殊的调用方法。
代码示例:
class Test(object): def __init__(self, a, b): # 构造器在实例创建时进行属性的初始化
self.a = int(a)
self.b = int(b) def abc(self, c): # 实例方法
print self.a + self.b + int(c) # 因为self是自动传递的,所以我们可以在实例方法中调用实例的属性 a = Test(123, 321) # 我们只要为 a 和 b 传参就行了
a.abc(666) # 同样的,只要为 c 传参
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQwAAAAjCAIAAADuY6OTAAAEG0lEQVR4nO2by5HjIBCGOyxC2ERMGHIEy02n3Qy4mrui0EUZOAn2AIhXY7DG8o6n/q+2XLa2oRuafhjXkO1zV2IiuhJdSa5tmVlt8bORYQhdpRlQ4lkl6SfEHdsiaMp1JTaLZeMsPMohC09kxDuZsDTeO9LYTc1jAw8aFtzR2rTHm3lXl6XnsRGZr0JdiU3NQt2ttdauUjQNSsSsF3br3xbx8FRtakn+98ARTLbJaPLDVxVsNmG6ysJRvmzhiQx6x2N0SBn7Kk5bTtTlsxiXK9+0mbkHnx7VD5I0ASfKquVti8icNBgkxTwHdi0dUg7Pdqe08MD8xyw8j/uod7xwndpPWk6qy1qjSWrJ1Kv3bOYxLXFUP0jGFRiZZotVZi2Q/yiNy/dXIn3zb9y/6DOlZqJrzPq+m3Knwc1TyTjBqpqpXCC10MiJSEs5hXneYWEGM2pWmx9uGJmaZ9yfpnYuSGKHnFcArz3sifEP26NKXW7b70okprrZxCxI/1Ez0SzEREJfxOR3bFcXDa52tZTh7Mk9eGuswrede7uej3plkFijk+629l/sB4yqvRX3IhxZ9zwky1gHahm/zvJEmqU8W6WFkzT5zGdamLMXgV2pO0Zpk13LFIwHSZ7amSCpp6q1r5ImYvuFR7r8PEaGAEh3jPTNrtJnB/fa6gvYXR2p88w8jVXwMz/Xbtnt/rBdedT52P0cG815q2XuyJvUAREjH+8XM895FnJ7NeU1yj1MiwYrk3If9U6e2tvHIq1atfbWEcxrHaOrqDaZ9pv/mL4WRj62ucrFZe0dCKRYOg4FSfbVsHcNkvQzzRxDrMVmbRwvNk9nMpua9zPd68sLC4uZz7KQIznf/nCHShLbklqmZMw7RWrP115ddZTritqZE8mNynVtyyXkLyPdhGFmo+nFQVLbY9serGbOvj/HUf0gSS4ZB76/+n4mDKmbBKPzlB8k5RpTjlyzdpPp3VOZv79iwrtybTdroROYhZiouKR+vYX7OcjZb673mcWyhebbMDIsA94pU7u1dRfOXiWn2pM2PdmfahRfRrJva8aGzC21pInEb6KrlHp/dcU8/wmB29VSprGK1IP8KvbvSPoipuQ3Az9qJEieomgYSrgW6M3sFrZKzX+38LXUZeRn6HofLw+SFsnd0ffAX4Nkled7WQi+CW8LEgA+FQQJAB0QJAB0QJAA0AFBAkAHBAkAHRAkAHRAkADQAUECQIfRIDGy/CW692RTgoiIxCv+ZhaA/8dAkBhJRERJAAw82ZQIf78iESbgoxmsJEZSUTceP9mU2EMDUQI+m5OCpPUegM8DQQJAB7RbAHQ4KUjwxR38HMZvt5Lbq5EnuAIGPwX8mAhABwQJAB0QJAB0QJAA0AFBAkAHBAkAHRAkAHRAkADQ4R9cnxGS++phswAAAABJRU5ErkJggg==" alt="" />
这里,将引入一个绑定 (binding) 的概念,其主要和方法的调用有关。
首先,我们知道方法是类的属性,而不是实例的属性,在上篇博文类的属性和实例的属性中我们也讨论过这个问题。
其次,方法只有在其所属的类拥有实例时,才能被调用。当一个类存在实例后,方法才被认为是绑定到这个实例。没有实例的时候,方法是未绑定的。
最后,任何一个方法定义的第一个参数都是变量 self ,它表示调用此方法的实例对象。
很明显这里的绑定针对的是实例方法。因为如果没有实例的话,self 就无法传递,这将导致参数的不足,当然就无法调用了。
但是,我们可以自己传递 self 来调用未绑定的方法。调用未绑定的方法通常是在我们继承了一个父类后, 我们覆盖了父类中的某个方法,但是为了实现代码重用,我们又想在子类中调用父类的方法。单纯的复制父类中的代码明显不是一个好选择, 除了浪费系统资源之外,还有可能在复制的时候出错,而且以后修改父类的代码之后,还要修改相应子类中的代码,实在太低效,这个时候就是调用未绑定方法的场景。
代码示例:
class abc(object):
def __init__(self, a):
self.a = -int(a) class Test(abc):
def __init__(self, a, b):
abc.__init__(self, a) # 调用父类的构造器,并手动传递 self
self.b = b def fangfa(self):
print self.a + self.b # 属性 a 由父类的构造器创建,b 由子类构造器创建 a = Test(123, 321) # 我们只创建了子类的实例,而没有创建父类的实例
a.fangfa()
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAAvCAIAAADrS1Z3AAADGElEQVR4nO2awZW0IAyAUxYl/I1MynA64Obt74Dr5G4VXujAJtiDgIDoMDru+vLyvT3MuFEjnwnoLjiBNfDXCQjXIoKZc0KwHZQa7NkERoQOwNDZ49S4f4bXsyV40qoDeAI8AcftmF4n40cYdoEnfjAeIx4YPjso6PJzJTl7r2WGRzmU4YW02PHUBVvdKz0555wbcbsIkjDng+eBsIPaHRGrh+S3B4Zv0o+QFZlQXqMOOVM43CrDVk5neCGNdmbqgtMbP7nU1XWWPbBRcHGcA8OX7lLunrk52KXPZ3gdU6sd55yb6oLbr4ewS7rxPF3Ftum/Is119gQwL/9h/vGVh2C07gGeS7X5DjxfiZ8Fyxh/hWUX0XlAmiFhB2AQu3Cc38gwo7JXr20+zWcxaz6528icFezIJNPA+txLDyEdK2ldH10Y7nl7uEmX+lvHOFftwDSU41Jm2CHlR74yw5xYfPGkk1aG0hmnElPQLnjSqnvfop2ddlvcXrd00QGZvNCrDfCjD46wW9cK4friqxkuG6/LsDZWXd4b5o1psVZjUqZWO2RADQ2LrHfrtKQH1qcBrYrHjBBG48bQVOsji7G6jz7ezUNFhsWRr8qwRuLGiwkVrOIu65iSNjuTVh3S+8ekhrWG74Fhl3VjIZOXWojEcblhcYyzYFimFXNVGvP/33Kbp2fcz3AO6JUK8+6FGZpXNZn4dBePrAZbPGpnMVUa7JCZh+Urb7KKJlNSa5u/TMxwq8T/PMPv4svXXfyqMlmj3gP/Kiar+Htl+HXkXTRzRDBzRDBzRDBzRDBzRDBzRDBzRDBzRDBz9gQTJm94rFYwEzYSAhSbhNuxIdjLS/5go8IXQkByjhCUf/9MKIpvy04Fe5PVzy9ntQqCHaH6xr+2CRfQKHipYKtVqNfYo6V870uj4MWmejy86zBFp7Us3I1mweXmrQYu3ItP5+C4oEpWVskKTLgb+6voZYKNT0mLyeXBSTr0fZEXHcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcwRwcz5Aaz3crFa6JyJAAAAAElFTkSuQmCC" alt="" />
本来我们没有创建父类的示例,是无法调用父类的实例方法的,但是我们手动传递了实例方法需要的 self 参数,就可以实现调用了。
这里的顺序是,我们创建了 Test 的实例,其 self 是自动传递的,故 Test 的构造方法 __init__(self, a, b) 中 self 就代表实例 a,而我们又调用了父类的 abc.__init__(self, a) 这里的 self 就是子类的实例 a ,参数 a 就是我们传的 123,而父类中 self.a = -int(a) ;最后我们可在子类的方法中调用 self.a 这个属性。
类方法:
类方法其实和实例方法类似,不过其第一个参数一般是 cls (约定俗成)而不是 self。但是,如果我们直接将 self 换成 cls 来创建类方法是不对的,因为实例方法的首个参数也是任意的,只是统一使用 self 。python的解释器并没有说看见第一个参数是 cls 就知道这个是类方法,它还是将其当作是实例方法来对待,所以我们需要通过内建函数: classmethod() 来创建类方法。
代码示例:
class Test(object): def abc(cls):
print cls.__name__ # 打印类名 abc = classmethod(abc) # 通过普通的函数传参的方式创建类方法 a = Test()
Test.abc() # 类能调用
a.abc() # 实例也能调用
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAA7CAIAAABOuyC1AAAFOUlEQVR4nO2cy3HsNhBFOyyE4ESEMDgRPOy4sZ0Btuo9o+AG5b1qkoAXBEj8SIGcT8t+95RqSjPCp9HARTfIEekfAIAoJG0AAL879CcAQBT6+vryAAA5IEIAhIEIARDm2SJ0k1KTe7SVWdNAZPkZFpX8fAvfA1t6gh+e0tfdqGNnzvp7V/eUkaDDz6dEuDjrRnQjPe+XGU3SJ+tYhW76hJMu+dRNioa8r8Tm4IvSwqv8tFnvmZ2ssOYwO5q9M2NfxYuGxenYc9qxM+/m49v9oqfM+0nHvssJETozKnP33ns/631xJ8V8KLz4103qcNU6MyV/vbDEk2lgG3fW2USbOTZXWdjLwxa+kM7ZCWzb8zqKlw0nDQVuUtRclG9yZj6Dr63lfW+6cUKEaQBJzKrcV+Z7nSIs2rkwK2mVsnrmx4sZ6eMWvo577+yEwnVoetFw8lDAlrTVjXj7Hmde6+WybV1h0J8SYb8prNO+l+PTmiKGt5qXeHUjsp/hl+VnWxPGjES3LWqFbHNZbeFUVpZZClbR2OQFUgtZD0RW6yG28w4LMxq1RuPyY2dWpubMQsm254YItxNEHsFC79EnHD7cr1X2tbj9blRi6tKaGhXZv8xINCo1kLIfaggeW7vbDK68WpZp2ZPP4OfOKEJavh5nGvPe5Y187LOmQWtLdNPa1u28RISebXK6qNfHli+xqVfD+naIklg+j5v9FsfqMt43s02eyrVbWjhozlt+pYU5axBbO12WaXrIqcsU9Iuw2J5rEdZN1b3PmgZq5jtHfYV2WEeBpR4j++lnHXaf5XUvr2l6tSdPabSzM4qDltuzXKWd2dhZLwO37GZ2pVcvpqPe3Q/TuaPM0K86YdtaDcXbU7+kE7zB+ng+Gu28zsKWr4Zyrw3L8bhMyr13dspTyt6yS6Nu3fveEs9jdaOvIlpmvX+Gt+lrYeSxzdVeX+YOHULdQl9/7zvt5BmBMlN+RT3xxsULM99dRkvyvd09kppj43lnhM0dKCvjzLhq5rtzUWFh0fKrLGyR6CeIJ0bCLW2ry5T0zU59SknGXl3KKse19d5Y8a1aeV9u+oj74xIZtpbZ0pNFWNvj92ewajm7flHUOpjlYz8P2hQLLHj12i2KjusTId+LVeokim0esmJJPW+bhJ6zdL9xdkrL/P3HtmHfWseepoVLgVGpgYqbKM+3cF1nOeudlbVlNbl4+OFGmSYds9O6WFeegpq3OtLek2NS4p+qVjsMZqdl9jHyaKtpIPUrnprC65KM5Le4Wl4ty+yMIp3B9ijWM6r9UENyT2toeSM9E+bttPzM2rK/Myd9rV592TdmioSqpJUivpnVwr1QKW7hc+m9WPdf6+uncXrs7//a2rxde/wZhMtoWeT8WRaC/zf47igAwkCEAAgDEQIgDEQIgDAQIQDCQIQACAMRAiAMRAiAMBAhAMKcECFr2sDXSQB4Emf+lcmw96xJs/dszj2lxRkD1QLQ5EwkZL+K0DOfEVWsBQCoOHsmrOTkjCIiUmtk3LLW5TNksQAc8qAInVFRakGGzaCHSAjALg+KMA1zyQM18tgIEQJwwLMioffOLZEwXrJJS147SQLwW3BKhOH8lwW5+FlU3Po+PQDGDxEOAajAzXoAhIEIARAGIgRAGIgQAGEgQgCEgQgBEAYiBEAYiBAAYSBCAISBCAEQBiIEQBg83gIAYfB4CwCEweMtABAGj7cAQBg83gIAYfB4CwCEweMtABAGj7cAQBjcrAdAGIgQAGEgQgCEgQgBEAYiBEAYiBAAYf4FgPyk8kEgja4AAAAASUVORK5CYII=" alt="" />
当然,有同学在看到这段代码的时候想到了装饰器,实际上我们也可以使用装饰器的方法来创建类方法:
class Test(object):
@classmethod
def abc(cls):
print cls.__name__ # 打印类名
结果也是一样的,具体选择看个人喜好。
注意,因为使用了 classmethod()函数,其第一个参数 cls 是固定传递的,而且是代表当前的类。并没有实例方法中非绑定方法的调用形式。
静态方法:
静态方法其实就是类中的一个普通函数,它并没有默认传递的参数,在创建静态方法的时候,需要用到内置函数: staticmethod() 。
代码示例:
class Test(object): def abc():
print 'abc' abc = staticmethod(abc) @staticmethod
def xyz(a, b):
print a + b Test.abc() # 类调用
Test.xyz(1, 2) # 类调用
a = Test()
a.abc() # 实例调用
a.xyz(3, 4) # 实例调用
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAARYAAABSCAIAAAAekWzWAAAByElEQVR4nO3dwU3DMBiGYY+VhfA43sbLkGHCoSWpRGJX+oQQyvOckODQy6vfSW1cNiBQ/voDwP8mIYhICCISgoiEIPJmQr2WUkrtv/th4P95fwr1KiH4QUIQkRBELhNa21LK6wNQr6XWWkopS1uv/gju5iqhfea8/lBq37a1Lc+G1rY8fmdAcV/XC7nHS7hjxJxGpRzubjaF9kmz9fpYwZ1MoW1tTUvc02wKLR8fSylL+9x6a/3x6HOMnu9JdTwdwc3YnQARCUFEQhCREEQkBBEJQURCEJEQRCQEEQlBREIQuUjo2KZtMzaMnCdU932jx25s4MRsIedMEAwNEurVMg5mTCGITN/IaQhGZq8Tvo97A6emL7WNIBjx1SpEJAQRCUFEQhCREEQkBBEJQURCEJEQRCQEETd+Q8RdqxCREEQkBBE3fkPEjd8QceM3RNz4DRE3fkPE7gSISAgiEoKIhCAiIYhICCISgoiEICIhiEgIIhKCyFVC+0kgG+Bg5HKndnuG07s92HBtspBzigHGxgntswg4N0xIQTAzSqhX57phYpCQf40AcxKCiK9WISIhiEgIIhKCiIQgIiGISAgiEoKIhCAiIYh8ASo79nZ1qmD9AAAAAElFTkSuQmCC" alt="" />
注意,虽然静态方法没有默认参数, 但并不代表不能有参数。
总结:
1.实例方法需要至少一个默认参数 self。
2.类方法需要至少一个默认参数 cls。
3.静态方法不需要默认参数。
另外:方法也是属性,所以在类的内部,我们可通过 self.abc()、cls.abc() 的方式来调用类中的其他方法,当然要注意传参的问题。
用方法冒充字段:
有时候,我们的一个方法在经过一系列处理以后,返回的是一个数据,例如:
class Test: def __init__(self, a, b):
self.a = a
self.b = b def fangfa(self):
c = self.a + self.b
return c # 返回处理的结果数据 a = Test(1, 2)
b = a.fangfa() # 调用方法,得到返回值
print b
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAALYAAAAqCAIAAACRNjZrAAADEUlEQVR4nO2bz3mtIBDFKYsSXiOPMrQDdu5eB24ze6twQwc2QRYC8s87aPS+m8/z+7LINQMcmcOAJhEWgJeIC/owk5ST+WkvsxKdECNdIKjg8xW+BxrF8XlgLbJo2QnRC9ELNe/HDDoamZRvInp1YEZndSIBZpKiS8eKNLsZyRWe5ZTCG2nJThKsyGVHkTV6aGnIWMToQerFWmvtrPYNGIVZF7xOpZnkyzk1eop+eiIBi/7rVdHol/isvWby3RUKW/mxwhtpzI5jKyHhLppuh7FIvPiiySq6zit5o0Wyfk4kIG6SN0+ye3Kv+bnC+1has+OCO19lL7VI+4yQ6qI9Zd22Q/F3HxWta70XYvxy36xfm2KtByH6bcW7fWSdC3cayGPWwKKS6TQgVkiqE2JUqvP9vENhQqXVoE163EliSo74NTmFVCyynQ1CmB/9MotYGqNdrVS/VULSpdbwsfMJW6/7hbLVgDLG2uo+QlM+s7nCTlHa850KU0IBCIMuWo4U75uVmIx2i8QlxNYsUna1jX5go7FmeVmoX9V8G7JIY00rK/3VXZHqyvVKqpy+qsLt4n0Ka3PVpfVpvRgXjGpMzNKanfxBpqowVLJi9L1u3bjxgYg7+kaVfHc7FNUZp3lncqtrNIkxeggZ5fbjTGHW810Ka0TZdan1VUSGJmVMTlt2shKS3ntxwM/v68hDb8OpzVVy36QsjzSmy91HqnmzrZrDacAfeLM9O47592dban1tu60qdNMkpT9/3Khw/KqKCc/qoWc5mezVSxJTpSE7tXch7nG3+pogjBVG3xn7HFmpzKkV/zcTFO6Vmf+u8FrKEnKYay2yR/S88Bm4A3xSdT5L4efwHouAXwwsAhhgEcAAiwAGWAQwwCKAARYBDLAIYIBFAANnEVLCgzePz4T7exHpf+VitIRJHknzRkMKDnkmLRYhhW3mwaCKAIb2Jxp45KE0H1dJCXnFPyuB30b7Qy9KyEPBqzPAAIsABlgEMMAigAEWAQywCGCARQADLAIYYBHAAIsABlgEMMAigAEWAQzfqE7fXByve8EAAAAASUVORK5CYII=" alt="" />
但是,懒惰的程序员们想:我想要的只是和字段类似的数据,却要调用一个方法,有时候容易搞错,能不能用字段的形式获取数据呢?这样更加符合直觉。
可以,只有使用 property() 函数就可以了。同样的,这里也有两种创建方式,这里只演示装饰器的方式:
class Test: def __init__(self, a, b):
self.a = a
self.b = b @property
def fangfa(self):
c = self.a + self.b
return c a = Test(1, 2)
b = a.fangfa # 不用带括号了
print b
这样是实现了方法伪装成字段了。其实就是懒惰的程序员们不愿意多写一个括号,当然还有一些其他好处。
另外,函数要用返回值,不然就默认为 None 了。
如果在经典类中,我们就只能做到这样了。
但是,使用新式类的话,就能有更多的功能:
class Test(object): def __init__(self, a, b):
self.a = a
self.b = b @property
def fangfa(self):
c = self.a + self.b
return c @fangfa.setter
def fangfa(self, value):
self.a = value @fangfa.deleter
def fangfa(self):
print '属性已删除' a = Test(1, 2)
b = a.fangfa # 获得方法的返回值
print b
a.fangfa = 100 # 执行 fangfa.setter 修饰的方法,并让value = 100
print a.a
del a.fangfa # 执行 fangfa.deleter 修饰的方法
aaarticlea/png;base64,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" alt="" />
注意后面两个装饰器的名字。
另外,方法必须要先经过 property()函数的装饰后,才有后面两个装饰器的用法。
如果使用非装饰器的形式的话:
class Test(object): def __init__(self, a, b):
self.a = a
self.b = b def fangfa_get(self):
c = self.a + self.b
return c def fangfa_set(self, value):
self.a = value def fangfa_del(self):
print '属性已删除' fangfa = property(fangfa_get, fangfa_set, fangfa_del)
property(fget=None, fset=None, fdel=None, doc=None)
最后的 doc 是说明文档,看个人需要添加,可通过 Test.fangfa.__doc__ 进行访问。
关于方法就先说这么多,以后有需要再进行修改补充。
24.python中类的方法的更多相关文章
- Python中类的方法属性与方法属性的动态绑定
最近在学习python,纯粹是自己的兴趣爱好,然而并没有系统地看python编程书籍,觉得上面描述过于繁琐,在网站找了一些学习的网站,发现廖雪峰老师的网站上面的学习资源很不错,而且言简意赅,提取了一些 ...
- python中类__call__方法与@classmethod
实现了__call__方法的类就变成了一个可调用对象,可以像函数一样调用,callable(obj)就返回True,否则返回False. 参考:https://www.cnblogs.com/supe ...
- python中类中属性和方法的具体定义方法和使用
1. Python中类中特性分成属性和方法 属性和方法都分为私有和公有的,私有的只可以在本类中使用外部是无法访问的 2. 定义属性(成员变量)的语法格式(公有属性/私有属性) class 类名: de ...
- python中类的定义、实例化、封装以及私有变量/方法
1. 定义类 python中定义一个类的格式如下: class MyClass(object): def __init__(self,data1,data2): self.__data1=data1 ...
- Python中类的相关介绍
本文主要介绍python中类的概念性内容,如类的定义.说明及简单使用 1. 类的简单介绍 1 # -*- coding:utf-8 -*- 2 # Author:Wong Du 3 4 ''' 5 - ...
- python类及其方法
python类及其方法 一.介绍 在 Python 中,面向对象编程主要有两个主题,就是类和类实例类与实例:类与实例相互关联着:类是对象的定义,而实例是"真正的实物",它存放了类中 ...
- [Python]读写文件方法
http://www.cnblogs.com/lovebread/archive/2009/12/24/1631108.html [Python]读写文件方法 http://www.cnblogs.c ...
- Python数据类型及其方法详解
Python数据类型及其方法详解 我们在学习编程语言的时候,都会遇到数据类型,这种看着很基础也不显眼的东西,却是很重要,本文介绍了python的数据类型,并就每种数据类型的方法作出了详细的描述,可供知 ...
- Python中类的__init__继承
Python中类的__init__继承 概念: 定义父类 In [10]: class Person: ....: def __init__(self,name,age,sex): ....: sel ...
随机推荐
- Java基础-Java中的堆内存和离堆内存机制
Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- python3中__get__,__getattr__,__getattribute__的区别
__get__,__getattr__和__getattribute都是访问属性的方法,但不太相同. object.__getattr__(self, name) 当一般位置找不到attribute的 ...
- 一个ssm综合小案例-商品订单管理----写在前面
学习了这么久,一直都是零零散散的,没有把知识串联起来综合运用一番 比如拦截器,全局异常处理,json 交互,RESTful 等,这些常见技术必须要掌握 接下来呢,我就打算通过这么一个综合案例把这段时间 ...
- Struts2_day02
一.内容大纲 1 结果页面配置 (1)全局结果页面 (2)局部结果页面 - 配置全局也配置局部,最终局部为准 (3)result标签type属性 - 默认值 dispatcher做转发 - redir ...
- ReactJS -- 初学入门
<!DOCTYPE html> <html> <head> <script src="build/react.js"></sc ...
- 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序
[题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...
- 第9月第27天 AVAssetExportSession AVAssetExportPresetMediumQuality
1. AVAssetExportPresetMediumQuality和 AVAssetExportPreset960x540 码率相差很大,视频大小也会相差很大 AVAssetExportPrese ...
- [Alg::DP] 袋鼠过河
一道简单的动态规划问题. 题目来源:牛客网 链接:https://www.nowcoder.com/questionTerminal/74acf832651e45bd9e059c59bc6e1cbf ...
- 从消费者角度评估RestFul的意义
相关博文: 从消费者角度评估RestFul的意义 SpringBoot 构建RestFul API 含单元测试 REST是目前业界相当火热的术语,似乎发布的API不带个REST前缀,你都不好意思和别人 ...
- 八、vue使用element-ui组件
element-ui组件 1.引入element import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element- ...