It is a continuation of Tips ① I will write it briefly, so I think that there are many things that are not strict, but if there are any mistakes, please comment ~
I've used the list type several times, so you know it, but it's an array with no size specified. Since it is a list object, it is okay to write ʻa = list () in addition to ʻa = []
.
The list type guarantees the order of the elements.
python:Python3.5.0
>>> a = [1,2,3,4,5,6,7,8,9]
>>> a.append(0) #Add element 0 after
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> a.insert(1,0) #Add element 0 to the specified index number
>>> a
[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> a[0] #Access element with index 0
1
>>> a[2] #Index accesses second element
2
>>> a[-1] #Index accesses the first element from the back(There is no 0)
0
>>> a[2:5] #Index accesses the 2nd to 5th elements
[2, 3, 4]
>>> a[2:-2] #Index accesses the second element from the first to the second
[2, 3, 4, 5, 6, 7, 8]
>>> a[2:-2:2] ##The index accesses the second element from the first to the second element in two steps.
[2, 4, 6, 8]
>>> b = [1.1, 1.2, 1.3, 1.4, 1.5]
>>> a.extend(b) #Joining lists
>>> a
[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1.1, 1.2, 1.3, 1.4, 1.5]
>>> a.pop() #Extract and delete the last element in the list
1.5
>>> a
[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1.1, 1.2, 1.3, 1.4]
>>> sorted(a) #sort(ascending order)
[0, 0, 1, 1.1, 1.2, 1.3, 1.4, 2, 3, 4, 5, 6, 7, 8, 9]
>>> sorted(a, reverse=True) #sort(descending order)
[9, 8, 7, 6, 5, 4, 3, 2, 1.4, 1.3, 1.2, 1.1, 1, 0, 0]
>>> len(a) #List length
16
I'm finally here ... This is unique to Python! !! The example given earlier in the for statement
python:Python3.5.0
>>> for i in range(1,10):
... a.append(i)
...
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
This can be written in one line.
python:Python3.5.0
>>> a = [i for i in range(1,10)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
It may be a little unpleasant at first glance, but it is quite convenient once you get used to it. By the way, it seems that the execution speed is faster than turning it with a for statement normally.
python:Python3.5.0
>>> a = [i for i in range(1,10) if i % 2 == 0]
>>> a
[2, 4, 6, 8]
>>> a = [i if i % 2 == 0 else i*i for i in range(1,10)]
>>> a
[1, 2, 9, 4, 25, 6, 49, 8, 81]
>>> a = [[j for j in range(i)] for i in range(1,10)]
>>> a
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
>>>
It can be obfuscated as much as you want, so moderately ...
Note that in Python objects are passed by reference. int / float / str / unicode (2.x series) looks like passing by value, but passing by reference of immutable object (it's not wrong ...). Well, you should be aware that list types are passed by reference (same for tuple types, set types, and dictionary types). So if you want to pass it as an argument to another variable or function, you need to copy it explicitly.
python:Python3.5.0
>>> a = [i for i in range(10)]
>>> b = a
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.pop()
9
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> b #b is also gone! !!
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> c = list(a) #This will be a copy(Different instances are generated)
>>> from copy import copy
>>> d = copy(c) #copy module can also be used
>>> a.pop()
8
>>> a
[0, 1, 2, 3, 4, 5, 6, 7]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> d
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>>
However, it should be noted that list (a)
and copy (a)
are shallow copies.
A shallow copy means that deep objects such as those with nested lists in the list are not copied, only the shallowest objects are copied and deeper objects are passed by reference (difficult to explain).
This is solved by using deepcopy in the copy module.
python:Python3.5.0
>>> a = [[j for j in range(4)] for i in range(4)]
>>> a
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> from copy import copy
>>> b = copy(a) #Shallow copy
>>> a[0].pop() #Pop from the list of elements
3
>>> a #Popped items disappear from the list of elements
[[0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> b #The popped one disappears from the list of copied list elements! !!
[[0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> from copy import deepcopy
>>> c = deepcopy(a) #Deep copy
>>> a[0].pop()
2
>>> a
[[0, 1], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> b
[[0, 1], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> c #Not disappear! !!
[[0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> a is b #The shallowest object instances are different
False
>>> a[0] is b[0] #Objects stored deeper than that will be the same instance by passing by reference
True
>>> a[0] is c[0] #deepcopy ↓ Objects are passed by value even for deep objects
False
>>>
The tuple type is represented by tuple. A tuple type is basically an arrangement of elements like a list, but once a value is stored, that value cannot be changed.
python:Python3.5.0
>>> a = tuple() #Empty tuple
>>> a = (1,2,3,4,5) #1~Tuples with 5 in order
>>> a[1] #Index accesses the first element
2
>>> a[1:3] #Access the elements whose index is from 1st to 3rd
(2, 3)
>>> a[0:5:2] #Access the elements with indexes 0 to 5 in step 2
(1, 3, 5)
>>> a[0] = 1 #An error occurs when assigning
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a = (1,) #Generate tuples
>>> a
(1,)
>>> a = (1) #,Without it, it won't be a tuple
>>> a
1
>>>
The only caveat is that it doesn't become a tuple without a comma.
The set type is represented by set. In the aggregate type, it is a collection of elements like the list type, but the order is not guaranteed as it does not allow duplicate elements.
python:Python3.5.0
>>> a = set() #Empty set
>>> a
set([])
>>> a = {i for i in range(10)} #Comprehension notation
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.add(10) #Add 10
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> a.add(10) #Add 10(It doesn't change because it already exists)
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> a = set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> a.remove(10) #Delete 10
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.remove(10) #Delete 10(It will be an error because it is not in the element)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 10
>>> a.add(10)
>>> a.discard(10) #Delete 10
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.discard(10) #Delete 10(If not, do nothing)
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = {1,2,3,4,5}
>>> b.issubset(a) #Is b a subset of a?
True
>>> b.issuperset(a) #Whether a is a subset of b
False
>>> c = {2,4,6,8,10,12,14,16,18,20}
>>> a.union(c) #Union of two sets
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20])
>>> a.intersection(c) #The intersection of two sets
set([8, 2, 4, 6])
>>> a.difference(c) #Element of a and not element of c(a-c)set
set([0, 1, 3, 5, 7, 9])
>>> a.symmetric_difference(c) #Exclusive OR of two sets
set([0, 1, 3, 5, 7, 9, 10, 12, 14, 16, 18, 20])
>>> a_copy = a.copy() #Copy of the set(Pass by value)
>>> a is a_copy #Different instances due to passing by value
False
>>> a == a_copy #The value is the same
True
>>> a_copy.update(c) #Add elements of other sets to the target set
>>> a_copy
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20])
>>> a_copy.pop() #Extract and delete any element
0
>>> a_copy.clear() #Remove all elements
>>> a_copy
set([])
>>>
** ~~ @ zakuro9715 pointed out and added and corrected hashing ~~ **
** Fixed the hashing pointed out on Twitter **
It's important that the elements are hashed and sorted, as is the case when you want to avoid duplication of elements as a use of sets (maybe to eliminate duplication of elements, maybe).
This is because the hash table is used when scanning the elements, so on average you can go with O (1) *, but otherwise it will be O (N). In other words, it works best when you do something like ʻa in b. The list type requires N × len (b) scans if you do something like ʻa in b
in N loops because the elements are not hashed.
On the other hand, aggregate (and dictionary-type keys) are hashed, so no such scan is done.
Therefore, if there are many loops and many elements, it is recommended to cast to a set type and then judge the condition such as ʻa in b`.
The dictionary type is represented by dict. In the dictionary type, it is stored as a key / value pair.
** In response to @ zakuro9715's point, I added and corrected the key settings ** The ~~ key (or value) can be set on any object. ~~ The key can be set ** if it is a hashable object **. (For example, you cannot set a dict that has a dict as a key) Any object can be set for the value.
python:Python3.5.0
>>> a = dict() #Generate empty dictionary type
>>> a = {str(i)+u"Th": i*i for i in range(10)}
>>> a
{'First': 1, '0th': 0, '7th': 49, '4th': 16, '8th': 64, '6th': 36, '9th': 81, 'Fifth': 25, 'The second': 4, 'The third': 9}
>>> a["0th"] #"0th"Get the value of the key
0
>>> a["Fifth"] #"Fifth"Get the value of the key
25
>>> a["10th"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: '10th'
>>> a.get(u"10th") #"10th"Get the value of the key(No but returns None instead of an error)
>>> a.get(u"10th", 100) #"10th"Get the value of the key. If not, the value set in the second argument is returned.
100
>>> a.get(u"9th", "100") #"9th"Get the value of the key. If not, the value set in the second argument is returned.
81
>>> a.keys() #Dict the key_Return as an object called keys (list in 2 series)
dict_keys(['4th', 'The third', 'Fifth', 'The second', '8th', '0th', '9th', 'First', '7th', '6th'])
>>> a.values() #Dict the value_Return as an object called values (list in 2 series)
dict_values([16, 9, 25, 4, 64, 0, 81, 1, 49, 36])
>>> a.items() #Dict the tuple of keys and values_Return as an object called items (list in 2 series)
dict_items([('4th', 16), ('The third', 9), ('Fifth', 25), ('The second', 4), ('8th', 64), ('0th', 0), ('9th', 81), ('First', 1), ('7th', 49), ('6th', 36)])
>>> "First" in a #Check if there is a key
True
>>> del a["0th"] #Delete the value of the corresponding key
>>> a.pop(u"First") #Get the value of the corresponding key and delete it
1
>>> a.popitem() #Get and delete any item
('4th', 16)
>>> a
{'The third': 9, 'Fifth': 25, 'The second': 4, '8th': 64, '9th': 81, '7th': 49, '6th': 36}
>>> b = a #Pass by reference
>>> c = a.copy() #Pass by value
>>> a is b #Same instance
True
>>> a is c #Different instances
False
>>> a == c #The value is the same
True
>>> a.clear() #Delete all
>>> a
{}
>>> b #Deleted because it is the same instance
{}
>>> c #It doesn't change because it's a different instance
{'9th': 81, 'Fifth': 25, 'The second': 4, '8th': 64, 'The third': 9, '7th': 49, '6th': 36}
>>>
>>> a = {str(i)+"Th": i*i for i in range(10)} #Dictionary comprehension
>>> a_copy = a.copy()
>>> a_copy.update({"0th": 10})
>>> a_copy["0th"]
10
>>>
There are many useful ways to count and iterate, especially in lists and dictionaries, so here are some that you might use with your own judgment and prejudice.
python:Python3.5.0
>>> a = [i for i in range(1,6)]
>>> #Output with index number
>>> for i, num in enumerate(a):
... print "{}Element of the second index:{}".format(i, num)
...
0th index element: 1
First index element: 2
Second index element: 3
Third index element: 4
Fourth index element: 5
>>> #Iterate two lists at the same time
>>> b = [str(i)+u"Second index" for i in range(5)]
>>> for a_num, b_num in zip(a, b):
... print(b_num+u":"+str(a_num))
...
0th index: 1
1st index: 2
Second index: 3
Third index: 4
4th index: 5
>>> c = [[j**i for j in range(1,5)] for i in range(1,5)]
>>> c
[[1, 2, 3, 4], [1, 4, 9, 16], [1, 8, 27, 64], [1, 16, 81, 256]]
>>> #Can also be used for transposition
>>> c_t = [[i, j, k, l] for i, j, k, l in zip(*c)]
>>> c_t
[[1, 1, 1, 1], [2, 4, 8, 16], [3, 9, 27, 81], [4, 16, 64, 256]]
>>>
>>> from itertools import product, permutations, combinations, combinations_with_replacement
>>> #Behavior when nesting for statements(You can specify the nesting depth with repeat)
>>> for pear in product(a, repeat=2):
... print(pear)
...
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(2, 5)
(3, 1)
(3, 2)
(3, 3)
(3, 4)
(3, 5)
(4, 1)
(4, 2)
(4, 3)
(4, 4)
(4, 5)
(5, 1)
(5, 2)
(5, 3)
(5, 4)
(5, 5)
>>> #Permutation that does not allow covering
>>> for pear in permutations(a, 2):
... print(pear)
...
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 1)
(2, 3)
(2, 4)
(2, 5)
(3, 1)
(3, 2)
(3, 4)
(3, 5)
(4, 1)
(4, 2)
(4, 3)
(4, 5)
(5, 1)
(5, 2)
(5, 3)
>>> #A combination that does not allow covering
>>> for pear in combinations(a, 2):
... print(pear)
...
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 3)
(2, 4)
(2, 5)
(3, 4)
(3, 5)
(4, 5)
>>> #Combination that allows for covering
>>> for pear in combinations_with_replacement(a, 2):
... print(pear)
...
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 2)
(2, 3)
(2, 4)
(2, 5)
(3, 3)
(3, 4)
(3, 5)
(4, 4)
(4, 5)
(5, 5)
>>>
python:Python3.5.0
>>> from itertools import combinations
>>> from collections import defaultdict, Counter
>>>
>>> #Creating a dictionary with nested dictionaries
>>> a = {}
>>> for key, val in combinations([i for i in range(6)], 2):
... if key not in a:
... a[key] = {}
... a[key][val] = key*val
...
>>> a
{0: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}, 1: {2: 2, 3: 3, 4: 4, 5: 5}, 2: {3: 6, 4: 8, 5: 10}, 3: {4: 12, 5: 15}, 4: {5: 20}}
>>>
>>> a = defaultdict(dict)
>>> for key, val in combinations([i for i in range(6)], 2):
... a[key][val] = key*val
...
>>> a
defaultdict(<type 'dict'>, {0: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}, 1: {2: 2, 3: 3, 4: 4, 5: 5}, 2: {3: 6, 4: 8, 5: 10}, 3: {4: 12, 5: 15}, 4: {5: 20}})
>>>
>>>
>>> #To store the count for a key in a dictionary
>>> a = {}
>>> for key, val in combinations([i for i in range(6)], 2):
... if key in a:
... a[key] += val
... else:
... a[key] = val
...
>>> a
{0: 15, 1: 14, 2: 12, 3: 9, 4: 5}
>>> a = Counter()
>>> for key, val in combinations([i for i in range(6)], 2):
... a[key] += val
>>> a
Counter({0: 15, 1: 14, 2: 12, 3: 9, 4: 5})
>>>
If you are interested in other things, please see Reference.
Then about how to write a function. Here, as a basic function writing method, I will write about the function definition statement / argument writing method (default setting) / return value (return, yield).
python:Python3.5.0
>>> #The most basic way of writing
>>> def hello():
... print("Hello world!!")
...
>>> hello()
Hello world!!
>>>
>>> #How to write when there is an argument
>>> def hello_name(name):
... print("Hello {}!!".format(name))
...
>>> hello_name("Guido")
Hello Guido!!
>>>
>>> #How to write when the argument has a default value
>>> def hello_name(name="world"):
... print("Hello {}!!".format(name))
...
>>> hello_name()
Hello world!!
>>> hello_name("Guido")
Hello Guido!!
>>>
>>> #How to write when there is a return value
>>> def hello_return(name):
... return "Hello {}!!".format(name)
...
>>> result = hello_return("Guido")
>>> print(result)
Hello Guido!!
>>>
>>> #Return value(Generator type)How to write when there is
>>> def hello_yield(name):
... for s in name:
... yield s
...
>>> generater = hello_yield("Hello Guido!!")
>>> generater.next()
'H'
>>> generater.next()
'e'
>>> generater.next()
'l'
>>> generater.next()
'l'
>>> generater.next()
'o'
>>> generater.next()
' '
>>> generater.next()
'G'
>>> generater.next()
'u'
>>> generater.next()
'i'
>>> generater.next()
'd'
>>> generater.next()
'o'
>>> generater.next()
'!'
>>> generater.next()
'!'
>>> generater.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
As a beginner, the generator expression may be difficult to understand, but you don't have to think hard, just think "remember the previous call state and return the next state withnext ()
".
If there is no next state, an exception of StopIteration
class will be thrown, so it is better to control with try / except when actually using it.
python:Python3.5.0
>>> generater = hello_yield("Hello Guido!!")
>>> while True:
... try:
... result = generater.next()
... print(result)
... except StopIteration:
... break
...
H
e
l
l
o
G
u
i
d
o
!
!
>>>
First of all, about the basic way of writing a class, I will write it there because it is a little different between 2 series and 3 series.
python:Python2.7.9
>>> class Hello(object):
... prefix = "Hello "
... def hello(self, name="world"):
... print(self.prefix+name+"!!")
...
>>> HelloInstance = Hello()
>>> HelloInstance.hello()
Hello world!!
>>>
This is a two-system writing style that inherits the base class ʻobject, which is a new class style. Be sure to write
self in the first argument of the instance method
hello as a reserved word. This is to refer to yourself (instance), this in PHP. In other words, writing ʻInstance.method (val)
will be read as Class.method (self, val)
.
There is also an old class style, so you can write only class Hello:
without writing ʻobject. However, the new style and the old style have different specifications (inheritance priority / class method, static method / property), so the new class style is recommended. This is also because we made improvements without breaking the old specifications. On the other hand, in the 3rd series,
class Hello:` will be the new class style in the 2nd series.
The operation does not change, but I will write it for the time being.
python:Python3.5.0
>>> class Hello:
... prefix = "Hello "
... def hello(self, name="world"):
... print(self.prefix+name+"!!")
...
>>> HelloInstance = Hello()
>>> HelloInstance.hello()
Hello world!!
>>>
Strictly speaking, it is not a constructor, but Python has a method called when creating an instance called __init__
, and you can write constructor-like processing here.
python:Python3.5.0
>>> class Hello:
... def __init__(self, prefix="Hello "):
... self.prefix = prefix
... def hello(self, name="world"):
... print(self.prefix+name+"!!")
...
>>> HelloInstance = Hello()
>>> HelloInstance.hello()
Hello world!!
>>> HelloInstance.hello("Guido")
Hello Guido!!
>>> HelloInstance = Hello("Hey ")
>>> HelloInstance.hello("Guido")
Hey Guido!!
>>>
By the way, there is a method called __new__
that is called before __init__
.
It returns its own instance, and __init__
is executed when its own instance is returned.
You can customize __new__
to return an instance other than yourself, but there is no benefit. .. ..
Well, it's not completely out of the question, and you can write a metaclass, but is it for beginners? I feel like that, so I will omit it.
(Tips for getting out of beginners / Tips for intermediate users will be written in another article)
In Python, if you define a method in a class, it is an instance method unless otherwise specified.
As mentioned earlier, the first argument of the instance method is self
, which points to your own instance.
However, you can also write class methods and static methods.
The differences in operation as well as how to write instance methods, class methods, and static methods are shown below, but you may not understand it unless you understand object orientation in the first place.
python:Python3.5.0
>>> class Hello:
... prefix = "Hello "
... def __init__(self, prefix=None):
... if prefix:
... self.prefix = prefix + " "
... def hello(self, name="world"):
... """
...Instance method: The first argument is self
... """
... print(self.prefix+name+"!!")
... @classmethod
... def hello_cls(cls, name="world"):
... """
...Class method: The first argument is cls
... """
... print(cls.prefix+name+"!!")
... @staticmethod
... def hello_stc(name="world"):
... """
...Static method: The first argument is not a reserved word
... """
... print(name+"!!")
... @classmethod
... def set_class_prefix(cls, prefix):
... cls.prefix = prefix + " "
...
>>> HelloInstance1 = Hello("Hey") #Instance prefix(self.prefix)To Hey
>>> HelloInstance1.hello("Guido!!")
Hey Guido!!!!
>>> HelloInstance1.hello_cls("Guido!!") #Since it is a class method, the prefix to access is the prefix of the class
Hello Guido!!!!
>>>
>>> HelloInstance2 = Hello("Hi") #Instance prefix(self.prefix)To Hey
>>> HelloInstance2.hello("Guido!!")
Hi Guido!!!!
>>> HelloInstance2.hello_cls("Guido!!")
Hello Guido!!!!
>>>
>>> HelloInstance2.set_class_prefix("I'm") #Rewrite class variables from HelloInstance2
>>> HelloInstance2.hello("Guido!!") #Instance variables do not rewrite
Hi Guido!!!!
>>> HelloInstance2.hello_cls("Guido!!") #Class variables are rewritten
I'm Guido!!!!
>>> #Another instance
>>> HelloInstance1.hello("Guido!!") #Instance variables do not rewrite
Hey Guido!!!!
>>> HelloInstance1.hello_cls("Guido!!") #Since it is a class variable, it will be rewritten! !!
I'm Guido!!!!
>>>
>>> Hello.hello_stc() #Static methods can be called from a class
world!!
>>>
The point to note is that if you rewrite a class variable from a class method, the class variable of another instance will also change (it's a class variable, not an instance variable, so it's quite natural).
It is __
(two underscores) such as __name__, __init__, __new__, __call__
that you often see when using Python, but it is used for special methods.
Here are some common special methods:
Special method | function | Example of use |
---|---|---|
__doc__ | Document string | View the documentation on the object. object.__doc__ |
__name__ | Imported file name or executable file | When executing a file. if__name__ == '__main__' |
__dict__ | Contains the attributes of the object | Get object attributes from strings, etc. |
__init__ | Method called when instantiating | X = Class() |
__new__ | Factory class when creating a new instance of a lath | It is also possible to override and create a meta class |
__call__ | Method called when the function is executed | X() |
__del__ | Method called when destroying an object | del object |
__add__ | Addition(+)Methods called when using operators | Overrideable and customizable |
__iter__ | Method called during loop | for loop. Comprehension notation |
__getattr__ | Access to attributes | X.attr |
__setattr__ | Assignment to attribute | X.attr = x |
Multiple inheritance is possible in Python. Here is an example of multiple inheritance just in case.
python:Python3.5.0
>>> class Hello:
... prefix = "Hello "
... def say(self, name):
... return self.prefix + name
...
>>>
>>> class Hey:
... prefix = "Hey "
... def say(self, name):
... return self.prefix + name + "!"
...
>>>
>>> class HowAreYou(Hello, Hey):
... def __init__(self, name, *args, **kargs):
... #Parent class initialization
... #In this example the parent class__init__Nothing is executed because is not defined
... super(HowAreYou, self).__init__(*args, **kargs)
... self.name = name
... def output(self):
... greet = self.say(self.name)
... print(greet, "How are you?")
...
>>>
>>> X = HowAreYou("Guido")
>>> X.output()
('Hello Guido', 'How are you?')
>>>
As mentioned above, it's like creating a class by inheriting two or more classes. Well, if you explain here, you have to explain from object-oriented programming. I'll leave that to other articles.
However, what should be noted here is the movement when HowAreYou.output ()
is executed. In the case of multiple inheritance, attributes may conflict with each other.
In this example as well (intentionally), the say attributes conflict with each other.
In Python, it is decided which parent class is prioritized when multiple inheritance is performed.
Basically, ① has priority over ② in the order of ① "left to right" ② "bottom to top" (② has priority over ① in the old style class).
So in this case, HowAreYou.output ()
gives priority toHello.say ()
. Similarly, self.prefix
takes precedence over Hello.prefix
.
Of course, I think there are attributes that I want to have multiple inheritance but I don't want them to collide with each other (although I think it's better to design so that they don't have multiple inheritance, of course).
The function used at that time is ** Nameman Gring **.
Specifically, two underscores are prepended to the attribute name.
Then it will be automatically interpreted as _Class__attr
.
python:Python3.5.0
>>> class Hello:
... __prefix = "Hello "
... def __say(self, name):
... return self.__prefix + name
...
>>> class Hey:
... __prefix = "Hey "
... def __say(self, name):
... return self.__prefix + name + "!"
...
>>> class HowAreYou(Hello, Hey):
... def __init__(self, name, *args, **kargs):
... #Parent class initialization
... #In this example the parent class__init__Nothing is executed because is not defined
... super(HowAreYou, self).__init__(*args, **kargs)
... self.name = name
... def hello_output(self):
... greet = self._Hello__say(self.name) #Hello__Call say
... print(greet, "How are you?")
... def hey_output(self):
... greet = self._Hey__say(self.name) #Hey's__Call say
... print(greet, "How are you?")
...
>>> X = HowAreYou("Guido")
>>> X.hello_output() #Use Hello say
('Hello Guido', 'How are you?')
>>> X.hey_output() #Use Hey say
('Hey Guido!', 'How are you?')
>>> dir(X) #Show X attributes
['_Hello__prefix', '_Hello__say', '_Hey__prefix', '_Hey__say', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hello_output', 'hey_output', 'name']
>>>
As mentioned above, just add two underscores (__
) and the attribute name is preceded by the _class name
.
** I thought I wrote it, but this may not be something to teach beginners ʕº̫͡ºʔ **
Unlike Java, Python cannot hide attributes.
However, you can do something like that by using underscores.
As mentioned earlier, name mangling can be used to prevent attributes of the same name from colliding with each other in different classes.
Although it is not the original usage, you can hide (like) the attributes you want to hide by using this function.
Also, _x
and __x
have slightly different meanings (can be used properly), so I will explain them.
python:Python3.5.0
>>> class Hello:
... def __init__(self):
... self._prefix = "Hello" #1 underscore
... self.__prefix = "Hey" #2 underscores
...
>>> HelloInstance = Hello()
>>> HelloInstance._prefix #Underscore One attribute can be accessed
'Hello'
>>> HelloInstance.__prefix #Underscore Two attributes cannot be accessed as they are
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Hello' object has no attribute '__prefix'
>>> HelloInstance._Hello__prefix #Can be accessed according to the name mangling
'Hey'
>>>
If there is only one underscore, it will be accessible, so it is just a prefix to indicate a local variable as a coding standard.
However, in the case of two underscores, the name mangling automatically assigns a _class name
, so you cannot access it with the same name.
It cannot be completely hidden in this way, but it can be hidden in a pseudo manner.
I wrote it briefly, but I was tired, so I will continue with ③
Click here for Tips ① Click here for Tips ③
Recommended Posts