Correct Way to Write in Python

P

punk.sagar

Hi All,

Im new to Python. Im coming from C# background and want to learn Python.
I was used to do following thing in C# in my previous experiences. I want to know how do I implement below example in Python. How these things are done in Python.
Code:
public class Bank
{

public List<Customer> lstCustomers = new List<Customer>();
private string micrcode;

public void Bank()
{
customer
}

}

public class Customer
{
private srting customername;

public string CustomerName

{
get { return customername; }
set { customername = value; }
}
}

main()
{
Customer objCustomer = new Customer;
objCustomer.CustomerName = "XYZ"

Bank objBank = new Bank();
objBank.lstCustomer.Add(objCustomer);

}
 
P

Peter Otten

Hi All,

Im new to Python. Im coming from C# background and want to learn Python.
I was used to do following thing in C# in my previous experiences. I want
to know how do I implement below example in Python. How these things are
done in Python.
Code:
public class Bank
{

public List<Customer> lstCustomers = new List<Customer>();
private string micrcode;

public void Bank()
{
customer
}

}

public class Customer
{
private srting customername;

public string CustomerName

{
get { return customername; }
set { customername = value; }
}
}

main()
{
Customer objCustomer = new Customer;
objCustomer.CustomerName = "XYZ"

Bank objBank = new Bank();
objBank.lstCustomer.Add(objCustomer);

}

While I don't know C# I doubt that this is good C# code ;)
Here's a moderately cleaned-up Python version:

class DuplicateCustomerError(Exception):
pass

class Customer:
def __init__(self, name):
self.name = name

class Bank:
def __init__(self):
self.customers = {}
def add_customer(self, name):
if name in self.customers:
raise DuplicateCustomerError
customer = Customer(name)
self.customers[name] = customer
return customer

if __name__ == "__main__":
bank = Bank()
bank.add_customer("XYZ")

I'm assuming a tiny bank where every customer has a unique name and only one
program is running so that you can ignore concurrency issues.
 
S

Sagar Varule

(e-mail address removed) wrote:


Hi All,

Im new to Python. Im coming from C# background and want to learn Python..
I was used to do following thing in C# in my previous experiences. I want
to know how do I implement below example in Python. How these things are
done in Python.
Code:
[/QUOTE]

public class Bank [QUOTE]
{[/QUOTE]

public List<Customer> lstCustomers = new List<Customer>();[/QUOTE]
[QUOTE]
private string micrcode; 

public void Bank() 






public class Customer 

private srting customername; 

public string CustomerName 


get { return customername; }[/QUOTE]
[QUOTE]
set { customername = value; } 





Customer objCustomer = new Customer;[/QUOTE]
[QUOTE]
objCustomer.CustomerName = "XYZ" 
Bank objBank = new Bank(); [QUOTE]
objBank.lstCustomer.Add(objCustomer);[/QUOTE]
[QUOTE]
}[/QUOTE]



While I don't know C# I doubt that this is good C# code ;)

Here's a moderately cleaned-up Python version:



class DuplicateCustomerError(Exception):

pass



class Customer:

def __init__(self, name):

self.name = name



class Bank:

def __init__(self):

self.customers = {}

def add_customer(self, name):

if name in self.customers:

raise DuplicateCustomerError

customer = Customer(name)

self.customers[name] = customer

return customer



if __name__ == "__main__":

bank = Bank()

bank.add_customer("XYZ")



I'm assuming a tiny bank where every customer has a unique name and only one

program is running so that you can ignore concurrency issues.

Thanks a lot Peter. I appreciate your Help. You mentioned that C# code above is not good. If you can point me why it is not good, would help me learn new approaches as this type of Code I use to see long back(when i was fresher). There may be better approaches or concepts i am not aware of. If you can point me in that direction it would be gr8.
 
S

Steven D'Aprano

Hi All,

Im new to Python. Im coming from C# background and want to learn Python.
I was used to do following thing in C# in my previous experiences. I
want to know how do I implement below example in Python. How these
things are done in Python.

I am not an expert on C#, but I'll try to translate the following code to
Python.

Code:
public class Bank
{

	public List<Customer> lstCustomers = new List<Customer>();
	private string micrcode;

	public void Bank()
	{
		customer
	}

}

public class Customer
{
	private srting customername;
	public string CustomerName[/QUOTE]

Do you mean "private string" rather than "private srting"?

[QUOTE]
{
		get { return customername; }
		set { customername = value; }
	}
}

main()
{
	Customer objCustomer = new Customer;
	objCustomer.CustomerName = "XYZ"

	Bank objBank = new Bank();
	objBank.lstCustomer.Add(objCustomer);

}


Here is a literally translation, as best as I can understand the C# code.
(But note that this is not the best Python code.)


class Bank:
def __init__(self):
self.lstCustomers = [] # Empty list of customers.
self._micrcode = '' # Does this actually get used?

class Customer:
def __init__(self):
self._customername = ''

@property
def CustomerName(self):
return self._customername

@CustomerName.setter
def CustomerName(self, value):
if not instance(value, str):
raise TypeError('names must be strings')
self._customername = value


if __name__ == '__main__':
# Running as a script, call the main function.
objCustomer = Customer()
objCustomer.CustomerName = "XYZ"

objBank = Bank()
objBank.lstCustomers.append(objCustomer)



But this isn't how I would write it in Python. For starters, our naming
conventions are different. Everything in Python is an object, even simple
types like ints and strings, and even classes, so it isn't meaningful to
prefix instances with "obj".

We tend to avoid anything which even vaguely looks like Hungarian
Notation, so "lstCustomer" is right out. Instead, we use plural for
collections (lists, sets, dicts, whatever) of things, and singular for
individual instances.

Also, while we can use the "property" decorator to make computed
attributes, we very rarely do just to enforce private/public variables.
Our philosophy is, if you want to shoot yourself in the foot, we're not
going to stop you. (People spend far too much time trying to work around
private names in other languages for Python to spend too much effort in
this area.) Instead, we have "private by convention": names starting with
a single underscore are "private", so don't touch them, and if you do,
you have nobody but yourself to blame when you shoot yourself in the foot.

Similarly, the language doesn't spend much time enforcing type
restrictions. Python is a dynamic language, and type restrictions go
against that philosophy. If you have a good reason to put a non-string as
the customer name, you can do so, but don't come crying to me if you
break your code. So here is how I would write the above:



class Bank:
def __init__(self):
self.customers = []
self._micrcode = '' # Does this actually get used?

class Customer:
def __init__(self, name):
# This type-check is optional.
if not instance(name, str):
raise TypeError('names must be strings')
self.name = name


if __name__ == '__main__':
# Running as a script, call the main function.
customer = Customer("XYX")

bank = Bank()
bank.customers.append(customer)


The above is still not what I call professional quality -- no doc strings
(documentation), and the bank doesn't actually do anything, but it's a
start.
 
P

Peter Otten

Thanks a lot Peter. I appreciate your Help. You mentioned that C# code
above is not good. If you can point me why it is not good, would help me
learn new approaches as this type of Code I use to see long back(when i
was fresher). There may be better approaches or concepts i am not aware
of. If you can point me in that direction it would be gr8.

As I said, I don't know C# -- but I already tried to fix some of the
potential issues in my code snippet.

- A list is not the best choice to store the customers -- there should be a
lookup by some kind of ID (I picked the name to keep it simple)
- Is it really necessary to expose that container in a language that
provides "privacy"?
- Is there ever a customer without name/ID? I'd say no, so these should be
passed as constructor arguments.
- Renaming a customer is a delicate process, you may need to keep track of
the old name, the reason for the name, update your database etc., so I
wouldn't allow setting the attribute and instead add a method

Bank.rename_customer(...)

or

Bank.customers.rename_customer(...)

Asking to translate code might make sense if you are a wizzard in the
"other" language and want to see how a particular construct is written
idomatically in Python, but to rewrite very basic C# code in Python is a bit
like trying to learn a natural language by replacing one word after another
in a text with the word in the new language that you looked up in a dict.
The result tends to be underwhelming.

I recommend that you read the tutorial and then try to solve a simple task
in Python. Whenever you run into a problem you can come here for help.
Because there's a real problem behind your code there will be different ways
to solve it in Python, and you'll learn much more about the possibilites
Python has to offer while your code gradually becomes more idiomatic.
 
S

Sagar Varule

Hi All,

Im new to Python. Im coming from C# background and want to learn Python..
I was used to do following thing in C# in my previous experiences. I
want to know how do I implement below example in Python. How these
things are done in Python.



I am not an expert on C#, but I'll try to translate the following code to

Python.




Code:
[/QUOTE]
[QUOTE]
public class Bank 


	public List<Customer> lstCustomers = new List<Customer>();[/QUOTE]
[QUOTE]
private string micrcode; 

	public void Bank() 






public class Customer 

	private srting customername;[/QUOTE]
[QUOTE]
public string CustomerName[/QUOTE]



Do you mean "private string" rather than "private srting"?




[QUOTE]
{[/QUOTE]
[QUOTE]
get { return customername; }[/QUOTE]
[QUOTE]
set { customername = value; } 





	Customer objCustomer = new Customer;[/QUOTE]
[QUOTE]
objCustomer.CustomerName = "XYZ" 
	Bank objBank = new Bank(); [QUOTE]
objBank.lstCustomer.Add(objCustomer);[/QUOTE]
[QUOTE]
}[/QUOTE]





Here is a literally translation, as best as I can understand the C# code.

(But note that this is not the best Python code.)





class Bank:

def __init__(self):

self.lstCustomers = [] # Empty list of customers.

self._micrcode = '' # Does this actually get used?



class Customer:

def __init__(self):

self._customername = ''



@property

def CustomerName(self):

return self._customername



@CustomerName.setter

def CustomerName(self, value):

if not instance(value, str):

raise TypeError('names must be strings')

self._customername = value





if __name__ == '__main__':

# Running as a script, call the main function.

objCustomer = Customer()

objCustomer.CustomerName = "XYZ"



objBank = Bank()

objBank.lstCustomers.append(objCustomer)







But this isn't how I would write it in Python. For starters, our naming

conventions are different. Everything in Python is an object, even simple

types like ints and strings, and even classes, so it isn't meaningful to

prefix instances with "obj".



We tend to avoid anything which even vaguely looks like Hungarian

Notation, so "lstCustomer" is right out. Instead, we use plural for

collections (lists, sets, dicts, whatever) of things, and singular for

individual instances.



Also, while we can use the "property" decorator to make computed

attributes, we very rarely do just to enforce private/public variables.

Our philosophy is, if you want to shoot yourself in the foot, we're not

going to stop you. (People spend far too much time trying to work around

private names in other languages for Python to spend too much effort in

this area.) Instead, we have "private by convention": names starting with

a single underscore are "private", so don't touch them, and if you do,

you have nobody but yourself to blame when you shoot yourself in the foot..



Similarly, the language doesn't spend much time enforcing type

restrictions. Python is a dynamic language, and type restrictions go

against that philosophy. If you have a good reason to put a non-string as

the customer name, you can do so, but don't come crying to me if you

break your code. So here is how I would write the above:







class Bank:

def __init__(self):

self.customers = []

self._micrcode = '' # Does this actually get used?



class Customer:

def __init__(self, name):

# This type-check is optional.

if not instance(name, str):

raise TypeError('names must be strings')

self.name = name





if __name__ == '__main__':

# Running as a script, call the main function.

customer = Customer("XYX")



bank = Bank()

bank.customers.append(customer)





The above is still not what I call professional quality -- no doc strings

(documentation), and the bank doesn't actually do anything, but it's a

start.

Thanks Steven for your Time and Effort. You have cleared many doubts and concepts for that I was struggling, since I started learning python. But I amfalling in love for Python. Your explanation for private and public accessmodifier was awesome as I was having harding time finding why we dont haveaccess modifier for python....Thanks a lot
 
S

Sagar Varule

Sagar Varule wrote:










As I said, I don't know C# -- but I already tried to fix some of the

potential issues in my code snippet.



- A list is not the best choice to store the customers -- there should bea

lookup by some kind of ID (I picked the name to keep it simple)

- Is it really necessary to expose that container in a language that

provides "privacy"?

- Is there ever a customer without name/ID? I'd say no, so these should be

passed as constructor arguments.

- Renaming a customer is a delicate process, you may need to keep track of

the old name, the reason for the name, update your database etc., so I

wouldn't allow setting the attribute and instead add a method



Bank.rename_customer(...)



or



Bank.customers.rename_customer(...)



Asking to translate code might make sense if you are a wizzard in the

"other" language and want to see how a particular construct is written

idomatically in Python, but to rewrite very basic C# code in Python is a bit

like trying to learn a natural language by replacing one word after another

in a text with the word in the new language that you looked up in a dict.

The result tends to be underwhelming.



I recommend that you read the tutorial and then try to solve a simple task

in Python. Whenever you run into a problem you can come here for help.

Because there's a real problem behind your code there will be different ways

to solve it in Python, and you'll learn much more about the possibilites

Python has to offer while your code gradually becomes more idiomatic.

Thanks Peter for helping me out,
Your Questions and suggestions are thoughts provoking and will help me every time I write a new Class. I will keep your suggestions. I am happy and amazed that Im getting help from strangers, But I got none when I approached programmers in my office....Thanks a Lot...!!!!!
 
C

Chris Angelico

Your explanation for private and public access modifier was awesome as I was having harding time finding why we dont have access modifier for python....Thanks a lot

It's a huge saving in time and effort. The C++ convention is: Make
everything private, then hand-write getters and setters for them all,
just in case you want to put extra code onto them. (I don't know C#
but it seems to be pretty much the same.) The Python convention is:
We're all consenting adults. Make stuff public, then if you need to
add code to something, make a @property that simulates the old
behaviour.

Personally, I've started to adopt the Python style in my C++ code as
well. I use struct instead of class, avoid making anything private,
and document the things that must not be done - for instance, I
created a class that had one particular pointer that must never be
advanced other than by the provided member function, but may be
retarded. No reason to fiddle with member privacy even there.

(The same technique has benefit in a quite different area, too:
separation of code and data. Not in C++, but I have systems that let
me load new code into a running process, and there it's extremely
helpful to just do everything as a simple structure, and then the new
code can slide in and work with the old data structure, happily
extending it with whatever it now needs. Again, everything's public.)

ChrisA
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top