Re: Object in List : how?
Again, thank you so much for all your suggestions; it's even easier for me now to proceed with my coding with all the guidance in one place (this email thread). I highly appreciate all of your help. I love this python community :) Regards, -Irfan On Mon, Jul 25, 2022 at 12:38 PM Dennis Lee Bieber wrote: > On 23 Jul 2022 22:55:47 GMT, r...@zedat.fu-berlin.de (Stefan Ram) declaimed > the following: > > >Dennis Lee Bieber writes: > >> if len([node for node in nodelist if node.no == no1]): > >> print("Found at least one occurence") > > > > I'm not sure you need the "len"; an empty list already is falsy. > > > > Just wanted to be explicit for the OP. > > > -- > Wulfraed Dennis Lee Bieber AF6VN > wlfr...@ix.netcom.com > http://wlfraed.microdiversity.freeddns.org/ > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On Fri, 22 Jul 2022 23:28:11 -0500, Khairil Sitanggang declaimed the following: >class Node: >def __init__(self): >self.NO = 0 >self.A = 20 > >NODE = Node() >NODELIST = [] > Comment... The convention is that ALL CAPS is used to indicate something that is to be treated as a CONSTANT. Classes get capitalized initial letters. Names of variable data is traditionally all lower case, lower case with _ between "words" (eg: lower_case), or camel case (eg: camelCase). >NODE.NO = 10 >NODELIST.append(NODE) > >NODE.NO = 20 >NODELIST.append(NODE) > >NODE.NO = 30 >NODELIST.append(NODE) > > >NO1 = 20 >if NO1 not in NODELIST[:].NO ??? The [:], in this statement, just says "make a copy of nodelist". The /list/ does not have an attribute named "NO". You have to ask for each element IN the list. One convoluted way (I've not tested it) is: if len([node for node in nodelist if node.no == no1]): print("Found at least one occurence") This is a list comprehension; it loops over each element in nodelist, making a new list if the element attribute matches the criteria. Python treats 0 as "false" and if no element matched, the list created is empty, so len() is 0. Anything else implies a match was found. -- Wulfraed Dennis Lee Bieber AF6VN wlfr...@ix.netcom.comhttp://wlfraed.microdiversity.freeddns.org/ -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
“Private” properties are more simply / commonly designated by sticking an _ in front of the name. class Node: def __init__(self,a) self._a = a I recommend you read https://docs.python.org/3/tutorial/classes.html. That’s not to say properties don’t have their uses, but making things “private” isn’t a major one. — Gerard Weatherby | Application Architect NMRbox | NAN | Department of Molecular Biology and Biophysics UConn Health 263 Farmington Avenue, Farmington, CT 06030-6406 uchc.edu On Jul 25, 2022, 10:36 AM -0400, Khairil Sitanggang , wrote: *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** Thank you everyone. The specific requirements for that class: *(1)* Provide the values of the "input" (via constructors). *I think everyone agrees with the way it is implemented in the example. * *(2)* Provide other products such as *b* that can be of any type (array, object, etc.). It is like an "output" if you will. *I think everyone suggests that it should be designed such that people should not be able (inadvertently) to change the value from outside the class. I agree, as a matter of fact this is my intent as well.* *(3)* About the function calc(), my intent is NOT to expose it outside the class: it is "private". *And I see the way to do that from your suggestions. * Based on all your valuable suggestions, I should be able to accomplish the 3 goals. By the way, I am writing this code for finite element analysis (FEA): number crunching. Even though the final goal is to get the correct results, I still want to write it following the correct python "grammar" and style. Best regards, -Irfan On Mon, Jul 25, 2022 at 3:54 AM Peter Otten <__pete...@web.de> wrote: On 25/07/2022 02:47, Khairil Sitanggang wrote: Regarding your comment : " *However, usually object creation and initialization iscombined by allowing arguments to the initializer:*" , so which one of the two classes Node1, Node2 below is more common in practice? Option 2, I guess. Thanks, # option 1: class Node1: def __init__(self, a): self.a = a self.b = self.calculation() def calculation(self): r = self.a + 10 return r # option 2: class Node2: def __init__(self, a, b): self.a = a self.b = b self.b = self.calculation() def calculation(self): r = self.a + 10 return r nd1 = Node1(10) nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to calculation() An attribute that can be calculated from other attributes should never be modified through other means. Some day you may want b to become something else, write, for example, node = Node2(10, "twenty") and because by then you have forgotten about the calculation() call end up with a buggy script. But manually invoking the calculation() method is also bug prone. You have to remember to repeat it every time you change a: node = Node1(10) assert node.b == 20 # OK node.a = 20 assert node.b == 30 # fails, a and b are out of sync. The solution Python has to offer is called "property". Properties in their simplest form are calculated read-only attributes, i. e. when you write print(node.b) under the hood node.a + 10 is calculated. Here's how to change Node1 to turn b into such a property: class Node3a: def __init__(self, a): self.a = a def calculation(self): return self.a + 10 b = property(calculation) node = Node3a(42) print(node.b) # 52 node.a = 1 print(node.b) # 11 Often you are not interested in exposing both the calculation() method and the property. For cases when you only want to access the property Python provides a way to define the property with a "decorator": class Node3b: def __init__(self, a): self.a = a @property def b(self): return self.a + 10 When you compare the two classes you can see that I (1) renamed calculation() to b() and (2) replaced def b(self): ... b = property(b) with @property def b(self): ... thus avoiding the repetitons of the name. Are there any disadvantages to properties? What I presented as an advantage, that the value of the attribute is recalculated every time the attribute is accessed, may sometimes become a disadvantage, e. g. when it takes a very long time to calculate. In most cases that should not be a problem, though. -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gibw_ZRRGmldOXyvOxYalA9ApszdEvnBdHnTgNVTbgvDAks80irsggsw45ZkniBHx0YRieVHhKAyn1gR$ -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
Thank you everyone. The specific requirements for that class: *(1)* Provide the values of the "input" (via constructors). *I think everyone agrees with the way it is implemented in the example. * *(2)* Provide other products such as *b* that can be of any type (array, object, etc.). It is like an "output" if you will. *I think everyone suggests that it should be designed such that people should not be able (inadvertently) to change the value from outside the class. I agree, as a matter of fact this is my intent as well.* *(3)* About the function calc(), my intent is NOT to expose it outside the class: it is "private". *And I see the way to do that from your suggestions. * Based on all your valuable suggestions, I should be able to accomplish the 3 goals. By the way, I am writing this code for finite element analysis (FEA): number crunching. Even though the final goal is to get the correct results, I still want to write it following the correct python "grammar" and style. Best regards, -Irfan On Mon, Jul 25, 2022 at 3:54 AM Peter Otten <__pete...@web.de> wrote: > On 25/07/2022 02:47, Khairil Sitanggang wrote: > > Regarding your comment : " > > *However, usually object creation and initialization iscombined by > allowing > > arguments to the initializer:*" , so which one of the two classes Node1, > > Node2 below is more common in practice? Option 2, I guess. > > Thanks, > > > > > > # option 1: > > class Node1: > > def __init__(self, a): > > self.a = a > > self.b = self.calculation() > > > > def calculation(self): > > r = self.a + 10 > > return r > > > > # option 2: > > class Node2: > > def __init__(self, a, b): > > self.a = a > > self.b = b > > > > self.b = self.calculation() > > > > def calculation(self): > > r = self.a + 10 > > return r > > > > nd1 = Node1(10) > > nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to > > calculation() > > An attribute that can be calculated from other attributes should never > be modified through other means. Some day you may want b to become > something else, write, for example, > > node = Node2(10, "twenty") > > and because by then you have forgotten about the calculation() call end > up with a buggy script. But manually invoking the calculation() method > is also bug prone. You have to remember to repeat it every time you > change a: > > node = Node1(10) > assert node.b == 20 # OK > > node.a = 20 > assert node.b == 30 # fails, a and b are out of sync. > > The solution Python has to offer is called "property". Properties in > their simplest form are calculated read-only attributes, i. e. when you > write > > print(node.b) > > under the hood node.a + 10 is calculated. Here's how to change Node1 to > turn b into such a property: > > class Node3a: > def __init__(self, a): > self.a = a > def calculation(self): > return self.a + 10 > b = property(calculation) > > node = Node3a(42) > print(node.b) # 52 > > node.a = 1 > print(node.b) # 11 > > Often you are not interested in exposing both the calculation() method > and the property. For cases when you only want to access the property > Python provides a way to define the property with a "decorator": > > class Node3b: > def __init__(self, a): > self.a = a > @property > def b(self): > return self.a + 10 > > When you compare the two classes you can see that I > > (1) renamed calculation() to b() and > > (2) replaced > > def b(self): ... > b = property(b) > > with > > @property > def b(self): ... > > thus avoiding the repetitons of the name. > > Are there any disadvantages to properties? > > What I presented as an advantage, that the value of the attribute is > recalculated every time the attribute is accessed, may sometimes become > a disadvantage, e. g. when it takes a very long time to calculate. In > most cases that should not be a problem, though. > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 25/07/2022 02:47, Khairil Sitanggang wrote: Regarding your comment : " *However, usually object creation and initialization iscombined by allowing arguments to the initializer:*" , so which one of the two classes Node1, Node2 below is more common in practice? Option 2, I guess. Thanks, # option 1: class Node1: def __init__(self, a): self.a = a self.b = self.calculation() def calculation(self): r = self.a + 10 return r # option 2: class Node2: def __init__(self, a, b): self.a = a self.b = b self.b = self.calculation() def calculation(self): r = self.a + 10 return r nd1 = Node1(10) nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to calculation() An attribute that can be calculated from other attributes should never be modified through other means. Some day you may want b to become something else, write, for example, node = Node2(10, "twenty") and because by then you have forgotten about the calculation() call end up with a buggy script. But manually invoking the calculation() method is also bug prone. You have to remember to repeat it every time you change a: node = Node1(10) assert node.b == 20 # OK node.a = 20 assert node.b == 30 # fails, a and b are out of sync. The solution Python has to offer is called "property". Properties in their simplest form are calculated read-only attributes, i. e. when you write print(node.b) under the hood node.a + 10 is calculated. Here's how to change Node1 to turn b into such a property: class Node3a: def __init__(self, a): self.a = a def calculation(self): return self.a + 10 b = property(calculation) node = Node3a(42) print(node.b) # 52 node.a = 1 print(node.b) # 11 Often you are not interested in exposing both the calculation() method and the property. For cases when you only want to access the property Python provides a way to define the property with a "decorator": class Node3b: def __init__(self, a): self.a = a @property def b(self): return self.a + 10 When you compare the two classes you can see that I (1) renamed calculation() to b() and (2) replaced def b(self): ... b = property(b) with @property def b(self): ... thus avoiding the repetitons of the name. Are there any disadvantages to properties? What I presented as an advantage, that the value of the attribute is recalculated every time the attribute is accessed, may sometimes become a disadvantage, e. g. when it takes a very long time to calculate. In most cases that should not be a problem, though. -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 25/07/2022 12.47, Khairil Sitanggang wrote: > Regarding your comment : " > *However, usually object creation and initialization iscombined by allowing > arguments to the initializer:*" , so which one of the two classes Node1, > Node2 below is more common in practice? Option 2, I guess. > Thanks, > > > # option 1: > class Node1: > def __init__(self, a): > self.a = a > self.b = self.calculation() > > def calculation(self): > r = self.a + 10 > return r > > # option 2: > class Node2: > def __init__(self, a, b): > self.a = a > self.b = b > > self.b = self.calculation() > > def calculation(self): > r = self.a + 10 > return r > > nd1 = Node1(10) > nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to > calculation() Let's start with calculation() - even though it is not your specific question: Given that "self" makes it into an instance-method, it will have access to self.b! Accordingly, the intermediate variable "r" and its return serves no purpose - assuming calculation() is only used to produce a value for self.b - which would leave: def calculation( self ): self.b = self.a + 10 At which point, the method becomes pointless - may as well put its single line in-line within __init__() - as I say, with above assumptions. Some languages do expect that every identifier (data-attribute in this case) be declared (as to type) and probably also initialised with a value. Some languages, and some Style Guides require that all data-attributes are declared within the constructor/initialiser. Python requires neither of these. Accordingly, if the "b" argument will only ever be a "dummy", there is absolutely no need for it - indeed one could argue that its presence is confusing because it gives the impression than it could assume any value. (see elsewhere in this thread). So, with assumptions and short of facts, "option 1" seems better (with the additional consideration regarding calculation(), as above). -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 2022-07-24 at 19:47:38 -0500, Khairil Sitanggang wrote: > Regarding [Peter Otten's] comment : " > *However, usually object creation and initialization iscombined by allowing > arguments to the initializer:*" , so which one of the two classes Node1, > Node2 below is more common in practice? Option 2, I guess. No. Please use option 1. Another option would be to expose b as an optional parameter with a default value: class Node: def __init__(self, a, b=0): self.a = a self.b = self.calculation() if b == 0 else b There are other ways to write that particular assignment to b (because the default is 0), but the relevant concept for right now is that callers *can* supply a value for b, but that they don't *have* to: n1 = Node(a) # uses a default value for b n2 = Node(a, 22) # overrides the default; use 22 instead Designing APIs can be tricky, and it's not an exact science. -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
Regarding your comment : " *However, usually object creation and initialization iscombined by allowing arguments to the initializer:*" , so which one of the two classes Node1, Node2 below is more common in practice? Option 2, I guess. Thanks, # option 1: class Node1: def __init__(self, a): self.a = a self.b = self.calculation() def calculation(self): r = self.a + 10 return r # option 2: class Node2: def __init__(self, a, b): self.a = a self.b = b self.b = self.calculation() def calculation(self): r = self.a + 10 return r nd1 = Node1(10) nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to calculation() On Sun, Jul 24, 2022 at 2:23 AM Peter Otten <__pete...@web.de> wrote: > On 23/07/2022 06:28, Khairil Sitanggang wrote: > > Hello Expert: > > > > I just started using python. Below is a simple code. I was trying to > check > > if, say, NO1 is not in the NODELIST[:].NO > > How can I achieve this purpose? > > > > Regards, > > -Irfan > > > > > > class Node: > > def __init__(self): > > self.NO = 0 > > self.A = 20 > > > > NODE = Node() > > NODELIST = [] > > > > NODE.NO = 10 > > NODELIST.append(NODE) > > > > NODE.NO = 20 > > This just overwrites the attribute; the previous value 10 is lost. > > > NODELIST.append(NODE) > > > > NODE.NO = 30 > > This againoverwrites the attribute; the previous value 20 is lost. > > > NODELIST.append(NODE) > > > You are three times appending the *same* node to the list. > To create a new node you need to invoke the initializer: > > [I'm following a common convention and use lowercase names in my examples] > > nodelist = [] > > # first node > node = Node() > node.no = 10 > nodelist.append(node) > > # second node > node = Node() # this is crucial > node.no = 20 > nodelist.append(node) > > ... and so on. However, usually object creation and initialization is > combined by allowing arguments to the initializer: > > class Node: > def __init__(self, no, a): > self.no = no > self.a = a > > nodelist = [] > for no in [10, 20, 30]: > nodelist.append(Node(no, 20)) > > > NO1 = 20 > > if NO1 not in NODELIST[:].NO ??? > > You are checking if the list contains an item with a specific attribute > value, so you cannot use the nodelist directly, you need an intermediate > list that contains the attribute values: > > no1 = 20 > nos = [node.no for node in nodelist] > if no1 not in nos: > print("not found") > > There's one disadvantage to this approach. If the node list is huge > another huge list with the attribute values is built even though the > first item in the nodelist may already have the searched-for attribute > value. To avoid the overhead you could write a function: > > def contains_no(nodes, no): > for node in nodes: > if node.no == no: > return True > return False > > if not contains_no(nodelist, 20): > print("not found") > > But Python has something more elegant, a kind of /lazy/ /list/ called > "generator expression" where each item is calculated on demand. With > that you can write > > if 20 not in (node.no for node in nodelist): > print("not found") > > and your script will stop inspecting further nodes as soon as a matching > node is found. > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
Peter: Thanks for the explanation. It is clear and easy to understand for a beginner like me. I highly appreciate it. Regards, -Irfan On Sun, Jul 24, 2022 at 2:23 AM Peter Otten <__pete...@web.de> wrote: > On 23/07/2022 06:28, Khairil Sitanggang wrote: > > Hello Expert: > > > > I just started using python. Below is a simple code. I was trying to > check > > if, say, NO1 is not in the NODELIST[:].NO > > How can I achieve this purpose? > > > > Regards, > > -Irfan > > > > > > class Node: > > def __init__(self): > > self.NO = 0 > > self.A = 20 > > > > NODE = Node() > > NODELIST = [] > > > > NODE.NO = 10 > > NODELIST.append(NODE) > > > > NODE.NO = 20 > > This just overwrites the attribute; the previous value 10 is lost. > > > NODELIST.append(NODE) > > > > NODE.NO = 30 > > This againoverwrites the attribute; the previous value 20 is lost. > > > NODELIST.append(NODE) > > > You are three times appending the *same* node to the list. > To create a new node you need to invoke the initializer: > > [I'm following a common convention and use lowercase names in my examples] > > nodelist = [] > > # first node > node = Node() > node.no = 10 > nodelist.append(node) > > # second node > node = Node() # this is crucial > node.no = 20 > nodelist.append(node) > > ... and so on. However, usually object creation and initialization is > combined by allowing arguments to the initializer: > > class Node: > def __init__(self, no, a): > self.no = no > self.a = a > > nodelist = [] > for no in [10, 20, 30]: > nodelist.append(Node(no, 20)) > > > NO1 = 20 > > if NO1 not in NODELIST[:].NO ??? > > You are checking if the list contains an item with a specific attribute > value, so you cannot use the nodelist directly, you need an intermediate > list that contains the attribute values: > > no1 = 20 > nos = [node.no for node in nodelist] > if no1 not in nos: > print("not found") > > There's one disadvantage to this approach. If the node list is huge > another huge list with the attribute values is built even though the > first item in the nodelist may already have the searched-for attribute > value. To avoid the overhead you could write a function: > > def contains_no(nodes, no): > for node in nodes: > if node.no == no: > return True > return False > > if not contains_no(nodelist, 20): > print("not found") > > But Python has something more elegant, a kind of /lazy/ /list/ called > "generator expression" where each item is calculated on demand. With > that you can write > > if 20 not in (node.no for node in nodelist): > print("not found") > > and your script will stop inspecting further nodes as soon as a matching > node is found. > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
Thank you. On Sun, Jul 24, 2022 at 2:23 AM Peter Otten <__pete...@web.de> wrote: > On 23/07/2022 06:28, Khairil Sitanggang wrote: > > Hello Expert: > > > > I just started using python. Below is a simple code. I was trying to > check > > if, say, NO1 is not in the NODELIST[:].NO > > How can I achieve this purpose? > > > > Regards, > > -Irfan > > > > > > class Node: > > def __init__(self): > > self.NO = 0 > > self.A = 20 > > > > NODE = Node() > > NODELIST = [] > > > > NODE.NO = 10 > > NODELIST.append(NODE) > > > > NODE.NO = 20 > > This just overwrites the attribute; the previous value 10 is lost. > > > NODELIST.append(NODE) > > > > NODE.NO = 30 > > This againoverwrites the attribute; the previous value 20 is lost. > > > NODELIST.append(NODE) > > > You are three times appending the *same* node to the list. > To create a new node you need to invoke the initializer: > > [I'm following a common convention and use lowercase names in my examples] > > nodelist = [] > > # first node > node = Node() > node.no = 10 > nodelist.append(node) > > # second node > node = Node() # this is crucial > node.no = 20 > nodelist.append(node) > > ... and so on. However, usually object creation and initialization is > combined by allowing arguments to the initializer: > > class Node: > def __init__(self, no, a): > self.no = no > self.a = a > > nodelist = [] > for no in [10, 20, 30]: > nodelist.append(Node(no, 20)) > > > NO1 = 20 > > if NO1 not in NODELIST[:].NO ??? > > You are checking if the list contains an item with a specific attribute > value, so you cannot use the nodelist directly, you need an intermediate > list that contains the attribute values: > > no1 = 20 > nos = [node.no for node in nodelist] > if no1 not in nos: > print("not found") > > There's one disadvantage to this approach. If the node list is huge > another huge list with the attribute values is built even though the > first item in the nodelist may already have the searched-for attribute > value. To avoid the overhead you could write a function: > > def contains_no(nodes, no): > for node in nodes: > if node.no == no: > return True > return False > > if not contains_no(nodelist, 20): > print("not found") > > But Python has something more elegant, a kind of /lazy/ /list/ called > "generator expression" where each item is calculated on demand. With > that you can write > > if 20 not in (node.no for node in nodelist): > print("not found") > > and your script will stop inspecting further nodes as soon as a matching > node is found. > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 23/07/2022 06:28, Khairil Sitanggang wrote: Hello Expert: I just started using python. Below is a simple code. I was trying to check if, say, NO1 is not in the NODELIST[:].NO How can I achieve this purpose? Regards, -Irfan class Node: def __init__(self): self.NO = 0 self.A = 20 NODE = Node() NODELIST = [] NODE.NO = 10 NODELIST.append(NODE) NODE.NO = 20 This just overwrites the attribute; the previous value 10 is lost. NODELIST.append(NODE) NODE.NO = 30 This againoverwrites the attribute; the previous value 20 is lost. NODELIST.append(NODE) You are three times appending the *same* node to the list. To create a new node you need to invoke the initializer: [I'm following a common convention and use lowercase names in my examples] nodelist = [] # first node node = Node() node.no = 10 nodelist.append(node) # second node node = Node() # this is crucial node.no = 20 nodelist.append(node) ... and so on. However, usually object creation and initialization is combined by allowing arguments to the initializer: class Node: def __init__(self, no, a): self.no = no self.a = a nodelist = [] for no in [10, 20, 30]: nodelist.append(Node(no, 20)) NO1 = 20 if NO1 not in NODELIST[:].NO ??? You are checking if the list contains an item with a specific attribute value, so you cannot use the nodelist directly, you need an intermediate list that contains the attribute values: no1 = 20 nos = [node.no for node in nodelist] if no1 not in nos: print("not found") There's one disadvantage to this approach. If the node list is huge another huge list with the attribute values is built even though the first item in the nodelist may already have the searched-for attribute value. To avoid the overhead you could write a function: def contains_no(nodes, no): for node in nodes: if node.no == no: return True return False if not contains_no(nodelist, 20): print("not found") But Python has something more elegant, a kind of /lazy/ /list/ called "generator expression" where each item is calculated on demand. With that you can write if 20 not in (node.no for node in nodelist): print("not found") and your script will stop inspecting further nodes as soon as a matching node is found. -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
dn, Thanks for the good analogy and explanation. I need some time to digest it. Regards, -Irfan On Sat, Jul 23, 2022 at 6:55 PM dn wrote: > On 24/07/2022 09.57, MRAB wrote: > > On 23/07/2022 05:28, Khairil Sitanggang wrote: > >> Hello Expert: > >> > >> I just started using python. Below is a simple code. I was trying to > >> check > >> if, say, NO1 is not in the NODELIST[:].NO > >> How can I achieve this purpose? > >> > >> Regards, > >> -Irfan > >> > >> > >> class Node: > >> def __init__(self): > >> self.NO = 0 > >> self.A = 20 > >> > >> NODE = Node() > >> NODELIST = [] > >> > >> NODE.NO = 10 > >> NODELIST.append(NODE) > >> > >> NODE.NO = 20 > >> NODELIST.append(NODE) > >> > >> NODE.NO = 30 > >> NODELIST.append(NODE) > >> > >> > >> NO1 = 20 > >> if NO1 not in NODELIST[:].NO ??? > > > > No, you can't do it that way. You have to iterate through the list and > > check each member individually: > > > > if any(NO1 == N.NO for N in NODELIST): > > > > And another thing: you've created only 1 node, and you're changing it > > each time before adding it to the list, so the list ends up with 3 > > references to the _same_ object. > > +1 > > > Imagine the object (Node) was instead a person, and a bunch of us-people > get together in a room. You could shout (above the polite conversation) > "is Fred here?" and Fred will reply - or if Fred is elsewhere, silence > will reign. That works - but only because everyone knows their own name. > > Now imagine something like (my) grade school, where the teacher takes a > roll/register to note who is present for (or absent from) class. In this > case another staff-member could enter the room and instead of shouting > (which would be rude), can ask the teacher "is Fred here?". The teacher > is able to answer from the roll. > > The former case is (sort of) the solution proposed above - in looking > for Fred, you walk through the room, asking each person in-turn "are you > Fred?". > > The latter is the case for Node and what you were hoping to implement. > > Thus, an alternate approach is to keep a register of nodes. Note that > this is more than a list, because each element of the list (each node) > is also identified (on the list) by its name. So, two pieces of > (related) data: the id of the node, and the node itself - the name of > the person and the person him-/her-self. > > Assuming you only have one ID that will be used to access a node, > Python's built-in dict[ionary] data-structure will provide the advantage > of direct-access (instead of going through (on average) half the nodes, > asking each one in-turn, are you ... > > So: > > > NODE = Node() > > NODELIST = [] > > > > NODE.NO = 10 > > NODELIST.append(NODE) > > becomes: > > graph = dict{} # could be written as: graph = {} > node10 = Node( 10 ) > graph[ node.id ] = node10 > > or even: > > graph[ 20 ] = Node( 20 ) > > if you don't need lots of nodes 'hanging around' outside of the 'list' > (actually a dict) representing the graph. > > > Then: > > > NO1 = 20 > > if NO1 not in NODELIST[:].NO ??? > > becomes a single line: > > the_node_required = graph[ 20 ] > > where "20" is the search-criteria. > > Does that make sense? > > > If it does, and when you realise that you'd like to do more with the > graph than retrieve single nodes (and more-importantly, should you want > (or dare) to delve further into the depths of Object-Oriented > Programming) you could declare a second class (graph) containing a > number of "methods". If one of the methods implemented is __contains__() > then you could indeed ask: > > if 20 in graph: > > ie "is Fred in-class today?" > but just as we would ask "is Fred here?" rather than "is someone > identified by the name 'Fred' here?", it would seem better form to write: > > if node( 20 ) in graph: > > ie is there a node with the id of 20, somewhere within the graph? > > > Such might involve sub-classing OrderedDict, UserDict, or even UserList, > from the Collections library in the (provided/"batteries-included") > Python Standard Library: > https://docs.python.org/3/library/collections.html > > If needed, the extra methods you choose to implement might include such > functionality as connecting nodes 10 and 20 with a path/edge, being able > to traverse edges, and so-on... > > Thus, we've covered two categories of class/object: one, a 'data-class' > which contains data about a single node; the other a 'collection-class' > which contains multiple nodes making-up the graph. A useful distinction > and a common related-pair of data-constructs! > -- > Regards, > =dn > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 24/07/2022 09.57, MRAB wrote: > On 23/07/2022 05:28, Khairil Sitanggang wrote: >> Hello Expert: >> >> I just started using python. Below is a simple code. I was trying to >> check >> if, say, NO1 is not in the NODELIST[:].NO >> How can I achieve this purpose? >> >> Regards, >> -Irfan >> >> >> class Node: >> def __init__(self): >> self.NO = 0 >> self.A = 20 >> >> NODE = Node() >> NODELIST = [] >> >> NODE.NO = 10 >> NODELIST.append(NODE) >> >> NODE.NO = 20 >> NODELIST.append(NODE) >> >> NODE.NO = 30 >> NODELIST.append(NODE) >> >> >> NO1 = 20 >> if NO1 not in NODELIST[:].NO ??? > > No, you can't do it that way. You have to iterate through the list and > check each member individually: > > if any(NO1 == N.NO for N in NODELIST): > > And another thing: you've created only 1 node, and you're changing it > each time before adding it to the list, so the list ends up with 3 > references to the _same_ object. +1 Imagine the object (Node) was instead a person, and a bunch of us-people get together in a room. You could shout (above the polite conversation) "is Fred here?" and Fred will reply - or if Fred is elsewhere, silence will reign. That works - but only because everyone knows their own name. Now imagine something like (my) grade school, where the teacher takes a roll/register to note who is present for (or absent from) class. In this case another staff-member could enter the room and instead of shouting (which would be rude), can ask the teacher "is Fred here?". The teacher is able to answer from the roll. The former case is (sort of) the solution proposed above - in looking for Fred, you walk through the room, asking each person in-turn "are you Fred?". The latter is the case for Node and what you were hoping to implement. Thus, an alternate approach is to keep a register of nodes. Note that this is more than a list, because each element of the list (each node) is also identified (on the list) by its name. So, two pieces of (related) data: the id of the node, and the node itself - the name of the person and the person him-/her-self. Assuming you only have one ID that will be used to access a node, Python's built-in dict[ionary] data-structure will provide the advantage of direct-access (instead of going through (on average) half the nodes, asking each one in-turn, are you ... So: > NODE = Node() > NODELIST = [] > > NODE.NO = 10 > NODELIST.append(NODE) becomes: graph = dict{} # could be written as: graph = {} node10 = Node( 10 ) graph[ node.id ] = node10 or even: graph[ 20 ] = Node( 20 ) if you don't need lots of nodes 'hanging around' outside of the 'list' (actually a dict) representing the graph. Then: > NO1 = 20 > if NO1 not in NODELIST[:].NO ??? becomes a single line: the_node_required = graph[ 20 ] where "20" is the search-criteria. Does that make sense? If it does, and when you realise that you'd like to do more with the graph than retrieve single nodes (and more-importantly, should you want (or dare) to delve further into the depths of Object-Oriented Programming) you could declare a second class (graph) containing a number of "methods". If one of the methods implemented is __contains__() then you could indeed ask: if 20 in graph: ie "is Fred in-class today?" but just as we would ask "is Fred here?" rather than "is someone identified by the name 'Fred' here?", it would seem better form to write: if node( 20 ) in graph: ie is there a node with the id of 20, somewhere within the graph? Such might involve sub-classing OrderedDict, UserDict, or even UserList, from the Collections library in the (provided/"batteries-included") Python Standard Library: https://docs.python.org/3/library/collections.html If needed, the extra methods you choose to implement might include such functionality as connecting nodes 10 and 20 with a path/edge, being able to traverse edges, and so-on... Thus, we've covered two categories of class/object: one, a 'data-class' which contains data about a single node; the other a 'collection-class' which contains multiple nodes making-up the graph. A useful distinction and a common related-pair of data-constructs! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
Thank you. I did it as you said. Yes, I forgot to create a new object Node() for each of the 3 instances. The reason I wanted to do as I asked was that I expected Python provides that convenient feature (since it is a high level language). I use Matlab a lot and it is so rich of features that allow us to process object array in many different ways. Anyway, as I said, I just started playing with Python, and I like it so much. Thanks to Visual Studio Code making coding very enjoyable. Get Outlook for iOS<https://aka.ms/o0ukef> From: Python-list on behalf of MRAB Sent: Saturday, July 23, 2022 4:57:34 PM To: python-list@python.org Subject: Re: Object in List : how? On 23/07/2022 05:28, Khairil Sitanggang wrote: > Hello Expert: > > I just started using python. Below is a simple code. I was trying to check > if, say, NO1 is not in the NODELIST[:].NO > How can I achieve this purpose? > > Regards, > -Irfan > > > class Node: > def __init__(self): > self.NO = 0 > self.A = 20 > > NODE = Node() > NODELIST = [] > > NODE.NO = 10 > NODELIST.append(NODE) > > NODE.NO = 20 > NODELIST.append(NODE) > > NODE.NO = 30 > NODELIST.append(NODE) > > > NO1 = 20 > if NO1 not in NODELIST[:].NO ??? No, you can't do it that way. You have to iterate through the list and check each member individually: if any(NO1 == N.NO for N in NODELIST): And another thing: you've created only 1 node, and you're changing it each time before adding it to the list, so the list ends up with 3 references to the _same_ object. -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Object in List : how?
On 23/07/2022 05:28, Khairil Sitanggang wrote: Hello Expert: I just started using python. Below is a simple code. I was trying to check if, say, NO1 is not in the NODELIST[:].NO How can I achieve this purpose? Regards, -Irfan class Node: def __init__(self): self.NO = 0 self.A = 20 NODE = Node() NODELIST = [] NODE.NO = 10 NODELIST.append(NODE) NODE.NO = 20 NODELIST.append(NODE) NODE.NO = 30 NODELIST.append(NODE) NO1 = 20 if NO1 not in NODELIST[:].NO ??? No, you can't do it that way. You have to iterate through the list and check each member individually: if any(NO1 == N.NO for N in NODELIST): And another thing: you've created only 1 node, and you're changing it each time before adding it to the list, so the list ends up with 3 references to the _same_ object. -- https://mail.python.org/mailman/listinfo/python-list